フォーム(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'
]
]);
}
以上。
