フォーム(Form)による認証機能を追加する。
ユーザーテーブルは、前の記事を参考に。
AppController.phpのinitializeメソッドに認証関連のコンポーネントを設定。
public function initialize() { parent::initialize(); $this->loadComponent('Flash'); //認証 $this->loadComponent('Auth',[ 'authenticate' => [ 'Form' => [ 'fields' => [ 'username' => 'email', 'password' => 'password' ] ] ], 'loginAction' => [ 'controller' => 'Users', 'action' => 'login' ] ]); }
Authコンポーネントをロードして、認証方法(authenticate)として、Formを使って、usernameにemalを、passwordにpasswordのカラム名を使う。
ログインは、Usersコントローラーのloginアクションで行う。
これで、どのページに行っても、AppControllerクラスを継承しているページでは、Users->loginに飛ばされるようになる。
今のところ肝心のUsers->loginが無いので、追加する。
Usersコントローラーに、loginアクションを追加。
/** * ログインページ * @return type */ public function login() { if($this->request->is('post')){ $user = $this->Auth->identify(); if($user){ $this->Auth->setUser($user); return $this->redirect($this->Auth->redirectUrl()); } $this->Flash->error('ユーザー名かパスワードが間違ってまっせ'); } }
POSTメソッドで飛んできたら、認証を行う。
OKだったら、Authコンポーネントに、ユーザーをセットして、リダイレクトさせる。
間違ってたら、フラッシュメッセージにエラー内容を書く。
次はTemplate。
Template\Users\login.ctp ファイルを追加して、以下のように書く。
<h1>Login</h1> <?= $this->Form->create() ?> <?= $this->Form->input('email') ?> <?= $this->Form->input('password') ?> <?= $this->Form->button('Login') ?> <?= $this->Form->end() ?>
ちなみに、Formヘルパーを使って書くとFormの部分は、下記のようなHTMLになるが、別にヘルパー使わずに直接書いても良い。
<form method="post" accept-charset="utf-8" action="/users/login"> <div style="display:none;"> <input type="hidden" name="_method" value="POST"> </div> <div class="input email"> <label for="email">Email</label> <input type="email" name="email" id="email"> </div> <div class="input password"> <label for="password">Password</label> <input type="password" name="password" id="password"> </div> <button type="submit">Login</button> </form>
これで、トップページでも、何でも良いのでアクセスすると、ログイン認証ページ(/users/login)に飛ばされる。
ここで、前回パスワードハッシュ化を行ったユーザーでログインしてみる。
ログインに成功すると、入ろうとしたページへリダイレクトされる。間違えると、設定したフラッシュメッセージが表示される。
もし、
「あ、やっべユーザーなんだっけ?パスワード忘れちまった。新しく作るか。」
「ユーザー追加ページ /users/add へアクセスっと。」
「ダメだ。/user/loginに飛ばされてしまう・・・。」となった場合は、UserControllerに下記を追加する。
public function beforeFilter(\Cake\Event\Event $event) { parent::beforeFilter($event); $this->Auth->allow(['add']); }
beforeFileterメソッドを追加して、そこに、$this->Auth->allow([‘add’]); と記述する。
これは、UserControllerでアクションが実行される前にaddメソッドに関しては、認証を許可しておくよ。ということ。
これで、/user/add に認証なしでつながるようになる。
ちなみに、引数なしで、$this->Auth->allow()と書くと、全アクションが許可になる。
ログアウトもつける。
Userコントローラーに、logoutを追加
/** * ログアウト * @return type */ public function logout() { $this->Flash->success('ログアウトしました'); return $this->redirect($this->Auth->logout()); }
/user/logoutページへ行くと、ログアウトが実行されて、/user/loginページへリダイレクトされる。
認証は通ったけど、認証したユーザーによってできる事を分けたい。
などの場合に、authorizeを使用する。
まず、Authコンポーネントの初期化に以下のように一行追加する。
//認証 $this->loadComponent('Auth',[ 'authorize' => 'Controller' //これを追加する 'authenticate' => [
すると、認証したユーザーは、isAuthorizedを通るようになるので、下記のメソッドのようなものを追記する。
(下記はあくまで例 )
public function isAuthorized($user = null){ $action = $this->request->params['action'] // 一覧と詳細は認証さえ通ればだれでも許可 if (in_array($action, ['index','detail'])) { return true; } // それ以外は役割がadminだったら許可 if($user['role'] === 'admin') { return true; } // 抜けたものはとりあえず非許可 return false; }
ちなみに、このページだけ認証かけたいって場合は、下記のように条件で変えたりしてもいいかも。
if(//なにかページによる条件){ //認証 $this->loadComponent('Auth',[ 'authorize' => 'Controller', 'authenticate' => [ 'Form' => [ 'fields' => [ 'username' => 'email', 'password' => 'password' ] ] ], 'loginAction' => [ 'controller' => 'Users', 'action' => 'login' ] ]); }
以上。