私の愛しいアップルパイへ
CakePHPにはパスワード認証機能などを実装しやすくするAuthコンポーネントが標準で使えるようになっています。
もちろん認証まわりを独自に実装するのも良いですが、Authコンポーネントは柔軟なので、楽に実装できておすすめです。
Authコンポーネント自体は過去のバージョンからありましたが、3.xになってから大きく使い方が変わったので解説します。
Authコンポーネントの読み込みとセットアップ
さっそく使い方を見ていきましょう。まず、Authコンポーネントの読み込みと、挙動のセットアップからです。
ここでは最もよく使われるであろうForm認証を例に説明していきますが、AuthコンポーネントはBasic認証とDigest認証にも対応しています。独自に拡張すれば、他の認証方式にも対応できます。
まずはAppController.phpでAuthコンポーネントを読み込み、パラメーターで挙動を指定していきます。
public function initialize() { parent::initialize(); $this->loadComponent('Flash'); // Flashコンポーネント。エラーメッセージの表示などに使用 $this->loadComponent('RequestHandler'); // RequestHandlerコンポーネント。入力されたデータの取得などに使用 $this->loadComponent('Auth', [ // Authコンポーネントの読み込み 'authenticate' => [ 'Form' => [ // 認証の種類を指定。Form,Basic,Digestが使える。デフォルトはForm 'fields' => [ // ユーザー名とパスワードに使うカラムの指定。省略した場合はusernameとpasswordになる 'username' => 'mail', // ユーザー名のカラムを指定 'password' => 'pass' //パスワードに使うカラムを指定 ] ] ], 'loginRedirect' => [ // ログイン後に遷移するアクションを指定 'controller' => 'Tasks', 'action' => 'index' ], 'logoutRedirect' => [ // ログアウト後に遷移するアクションを指定 'controller' => 'Users', 'action' => 'login', ], 'authError' => 'ログインできませんでした。ログインしてください。', // ログインに失敗したときのFlashメッセージを指定(省略可) ]); }
▼その他の設定については以下のページをご参照ください。
Entityによるパスワードの暗号化処理
パスワードは暗号化して保存したいですよね。その場合はEntityで行います。
以下はUserEntity(Model/Entity/User.php)でパスワードハッシュ処理を実装したところです。
use Cake\Auth\DefaultPasswordHasher; 〜〜〜〜〜 〜〜〜〜〜 /** * パスワード保存時のハッシュ化 * @param string $password パスワード文字列 * @return string ハッシュ化されたパスワード */ protected function _setPassword($password) { return (new DefaultPasswordHasher)->hash($password); }
ここではCakePHPの標準で使えるDefaultPasswordHasherを使っています。ハッシュで使うsaltはapp.phpに記載されています。
/** * Security and encryption configuration * * - salt - A random string used in security hashing methods. * The salt value is also used as the encryption key. * You should treat it as extremely sensitive data. */ 'Security' => [ 'salt' => 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' ],
Entityで「_set○○」というprotectedメソッドを呼ぶことで、○○というカラムをデータベースに保存する直前に、値を編集できます。○○の部分はキャメル記法です。
パラメーターには、カラム名をキャメルバック記法で指定します。ここに保存しようとしていたデータが入ってきます。
上記では、_setPasswordとすることで、passwordを保存する前にハッシュ処理を行っています。
▼このあたりのEntityの動きは以下の公式ドキュメントに書かれています。
identifyメソッドによる認証処理の実装
実際に認証する処理を実装していきましょう。
ログイン時にPostされるアクションを実装していきます。ここではUsersController.phpのlogin()メソッドを使う想定で書いています。
protected function login() { $user = $this->Auth->identify(); // Postされたユーザー名とパスワードをもとにデータベースを検索。ユーザー名とパスワードに該当するユーザーがreturnされる if ($user) { // 該当するユーザーがいればログイン処理 $this->Auth->setUser($user); return $this->Auth->redirectUrl(); } else { // 該当するユーザーがいなければエラー throw new UnauthorizedException('メールアドレスかパスワードが間違っています'); } }
ハイライト箇所が実際のログイン処理です。
identify()を使うと、ユーザーから入力されたデータを$this->requestから冒頭で設定したユーザー名とパスワードを読み取り、データベースに該当するユーザーがいるか調べてくれます。
そして、該当するユーザーがいればそのユーザーオブジェクトを取得します。つまり、そのユーザーでログイン状態にすれば良いということです。
setUser()はセッション内にユーザー情報を保持してくれます。ちなみに、ここで保存されたデータは$this->Auth->user()で取得することができます。
redirectUrl()では、冒頭で設定したログイン後のURLにリダイレクトしてくれます。
これで最低限必要なログイン処理は実装できるはずです。
▼このあたりの処理は以下の公式ドキュメントに詳細な記述があります。
ログアウト処理の実装
続けてログアウト処理を実装しましょう。これはとても簡単です。
/** * ログアウト * @return bool */ public function logout() { $this->request->session()->destroy(); // セッションの破棄 return $this->redirect($this->Auth->logout()); // ログアウト処理 }
ハイライト箇所でログアウト処理と、冒頭で指定したログアウト後のURLへのリダイレクトを行っています。
allowメソッドによるログイン不要アクションの指定
ユーザー新規登録処理などのログイン不要なページを指定する方法を見ていきましょう。
ControllerのbeforeFilterでallow()の引数にアクション名を指定します。ここで指定されたアクションは、ログインせずに表示できるようになります。
/** * beforeFilter * @param Event $event イベントオブジェクト * @return void */ public function beforeFilter(Event $event) { parent::beforeFilter($event); $this->Auth->allow(['add', 'activate']); }
Authコンポーネントの公式参考資料
最後に、Authコンポーネントを使ううえで、参考になる記事を記載しておきます。
▼Authコンポーネントを使って認証機能を実装する公式のチュートリアルです。
▼Authコンポーネントの仕様が整理された公式文書です。
貴下の従順なる下僕 松崎より