ブログチュートリアル Part.2
CakePHP4のブログチュートリアルを進める。Part.2 book.cakephp.org
シンプルな認証と認可のアプリケーション
ユーザーに関連するコードを作成する
ログインユーザーを保持するためにUsersテーブルを作成する。 下記SQLをSQLite内で実行。
CREATE TABLE users ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, email VARCHAR(255), password VARCHAR(255), role VARCHAR(20), created DATETIME DEFAULT NULL, modified DATETIME DEFAULT NULL );
Usersテーブルを作成したので、Bake allする。
bin/cake bake all Users
認証の追加
認証用のプラグインをインストールする。
composer require "cakephp/authentication:^2.0"
パスワードハッシュの追加
パスワードを自動的にハッシュ化するためのメソッドをUserエンティティに追加する。
<?php protected function _setPassword($password) { if (strlen($password) > 0) { return (new DefaultPasswordHasher)->hash($password); } }
認証の設定
認証を有効にするため、下記二つのプラグインをApplication.php内で有効にする。
- AuthenticationService
- AuthenticationMiddleware
<?php use Authentication\AuthenticationService; use Authentication\AuthenticationServiceInterface; use Authentication\AuthenticationServiceProviderInterface; use Authentication\Middleware\AuthenticationMiddleware; use Psr\Http\Message\ServerRequestInterface;
アプリケーションクラスに認証インターフェースを実装する。
<?php class Application extends BaseApplication implements AuthenticationServiceProviderInterface {
インターフェースのメソッドを実装する。
<?php // src/Application.php public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue { $middlewareQueue // ... other middleware added before ->add(new RoutingMiddleware($this)) // add Authentication after RoutingMiddleware ->add(new AuthenticationMiddleware($this)); return $middlewareQueue; } public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface { $authenticationService = new AuthenticationService([ 'unauthenticatedRedirect' => '/users/login', 'queryParam' => 'redirect', ]); // 識別子をロードして、電子メールとパスワードのフィールドを確認します $authenticationService->loadIdentifier('Authentication.Password', [ 'fields' => [ 'username' => 'email', 'password' => 'password', ] ]); // 認証子をロードするには、最初にセッションを実行する必要があります $authenticationService->loadAuthenticator('Authentication.Session'); // メールとパスワードを選択するためのフォームデータチェックの設定 $authenticationService->loadAuthenticator('Authentication.Form', [ 'fields' => [ 'username' => 'email', 'password' => 'password', ], 'loginUrl' => '/users/login', ]); return $authenticationService; }
AppController内で認証用のコンポーネントをロードする。
<?php // src/Controller/AppController.php public function initialize(): void { parent::initialize(); $this->loadComponent('RequestHandler'); $this->loadComponent('Flash'); // Add this line to check authentication result and lock your site $this->loadComponent('Authentication.Authentication');
UsersController に以下のメソッドを実装する。
<?php public function beforeFilter(\Cake\Event\EventInterface $event) { parent::beforeFilter($event); // ログインアクションを認証を必要としないように設定することで、 // 無限リダイレクトループの問題を防ぐことができます $this->Authentication->addUnauthenticatedActions(['login']); } public function login() { $this->request->allowMethod(['get', 'post']); $result = $this->Authentication->getResult(); // POSTやGETに関係なく、ユーザーがログインしていればリダイレクトします if ($result->isValid()) { // ログイン成功後に /article にリダイレクトします $redirect = $this->request->getQuery('redirect', [ 'controller' => 'Articles', 'action' => 'index', ]); return $this->redirect($redirect); } // ユーザーの送信と認証に失敗した場合にエラーを表示します if ($this->request->is('post') && !$result->isValid()) { $this->Flash->error(__('Invalid email or password')); } }
ログイン用のtemplate(login.php)を実装する。
<?php <div class="users form"> <?= $this->Flash->render() ?> <h3>Login</h3> <?= $this->Form->create() ?> <fieldset> <legend><?= __('ユーザー名とパスワードを入力してください') ?></legend> <?= $this->Form->control('email', ['required' => true]) ?> <?= $this->Form->control('password', ['required' => true]) ?> </fieldset> <?= $this->Form->submit(__('Login')); ?> <?= $this->Form->end() ?> <?= $this->Html->link("Add User", ['action' => 'add']) ?> </div>
認証が不要なアクションを定義する。
<?php // src/Controller/AppController.php で public function beforeFilter(\Cake\Event\EventInterface $event) { parent::beforeFilter($event); $this->Authentication->addUnauthenticatedActions(['index', 'view']); }
ログアウト
ログアウト用のアクションを Usersコントローラーに追加する。
<?php // src/Controller/UsersController.php で public function logout() { $result = $this->Authentication->getResult(); // POSTやGETに関係なく、ユーザーがログインしていればリダイレクトします if ($result->isValid()) { $this->Authentication->logout(); return $this->redirect(['controller' => 'Users', 'action' => 'login']); } }
こちらで、 /users/logout にアクセスするとログアウトが完了し、ログイン画面へリダイレクトされるようになる。