[CakePHP3] ざっくりとフォーム認証

フォーム(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)に飛ばされる。

CakePHP3-3-1

ここで、前回パスワードハッシュ化を行ったユーザーでログインしてみる。
ログインに成功すると、入ろうとしたページへリダイレクトされる。間違えると、設定したフラッシュメッセージが表示される。

もし、
「あ、やっべユーザーなんだっけ?パスワード忘れちまった。新しく作るか。」
「ユーザー追加ページ /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'
		]
	]);
}

 

以上。

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>