CakePHP4 には、ログイン処理を簡単に組み込める、Authenticationというユーザー認証のプラグインがあります。
しかしながら、authentication は、ログインができるか、できないか、というシンプルな機能であるため、
ユーザーごとに、ページのアクセス制御などができません。
これを実現するためには、Authorization を利用することで実現することができます。
日本のページがないので、わかりにくい部分もありますが、とても簡単に、ユーザーごとのアクセス制御ができます。
authorization のインストール
1 |
php composer.phar require "cakephp/authorization:^2.0" |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
[ec2-user@ip-172-31-1-131 html]$ composer require "cakephp/authorization:^2.0" ./composer.json has been updated Running composer update cakephp/authorization Loading composer repositories with package information Info from https://repo.packagist.org: #StandWithUkraine Updating dependencies Lock file operations: 1 install, 0 updates, 0 removals - Locking cakephp/authorization (2.2.0) Writing lock file Installing dependencies from lock file (including require-dev) Package operations: 1 install, 0 updates, 0 removals - Downloading cakephp/authorization (2.2.0) - Installing cakephp/authorization (2.2.0): Extracting archive Generating autoload files 55 packages you are using are looking for funding. Use the `composer fund` command to find out more! |
プラグインの設定
src/Application.php に以下の内容を追記します。
1 |
$this->addPlugin('Authorization'); |
Application クラスの修正
src/Application.php に以下の内容を追記します。
1 2 3 4 5 6 7 |
use Authorization\AuthorizationService; use Authorization\AuthorizationServiceInterface; use Authorization\AuthorizationServiceProviderInterface; use Authorization\Middleware\AuthorizationMiddleware; use Authorization\Policy\OrmResolver; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; |
AuthorizationServiceProviderInterface を implements するように追記します。
1 |
class Application extends BaseApplication implements AuthorizationServiceProviderInterface |
middleware() に、以下の内容を追記します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue { // Middleware provided by CakePHP $middlewareQueue->add(new ErrorHandlerMiddleware(Configure::read('Error'))) ->add(new AssetMiddleware()) ->add(new RoutingMiddleware($this)) ->add(new BodyParserMiddleware()) // If you are using Authentication it should be *before* Authorization. ->add(new AuthenticationMiddleware($this)); // Add the AuthorizationMiddleware *after* routing, body parser // and authentication middleware. ->add(new AuthorizationMiddleware($this)); return $middlewareQueue(); } |
src/Application.php に、以下のメソッドを追記します。
1 2 3 4 5 6 |
public function getAuthorizationService(ServerRequestInterface $request): AuthorizationServiceInterface { $resolver = new OrmResolver(); return new AuthorizationService($resolver); } |
src/Controller/AppController.php に、下記の内容を追記します。
1 |
$this->loadComponent('Authorization.Authorization'); |
ここまでで、必要な初期設定は完了となります。
アクセス制御
各メソッドに、アクセス制御を追記します。
例えば、edit に アクセスする権限をチェックする場合には、以下のようになります。
1 2 3 4 5 6 7 |
public function edit($id = null) { $memo = $this->Memo->get($id); $this->Authorization->authorize($memo, 'update'); // Rest of action } |
Policy の作成
CakePHP では、Policy を利用して、アクセス制御を行います。
src/Policy に、各Policyファイルを置いていきます。
Userの場合には、下記の場所に保存します。
src/Policy/MemoPolicy.php
1 2 3 4 5 6 7 8 9 |
<?php namespace App\Policy; use App\Model\Entity\User; use Authorization\IdentityInterface; class MemoPolicy { } |
bake でも生成することができます。
1 2 3 |
bin/cake bake policy --type entity Memo bin/cake bake policy --type table Memos |
Policy メソッドを追記します。
1 2 3 4 |
public function canUpdate(IdentityInterface $ident, Memo $memo) { return $ident->id == $memo->user_id; } |
Policy Scopes の生成
アクセス制御で、さらにデータごとに、制御する場合には、Policy Scopes を生成します。
1 2 3 4 5 6 7 8 9 |
amespace App\Policy; class MemosTablePolicy { public function scopeIndex($user, $query) { return $query->where(['Memos.user_id' => $user->getIdentifier()]); } } |
コントローラーでは、以下のように利用します。
1 2 |
$this->Authorization->authorize($query); $memos = $this->paginate($this->Authorization->applyScope($query)); |
CakePHP Authorization 2.x Cookbook
公式サイトには、日本語のページがありませんが、簡単に一読されると理解が深まると思います。