CakePHP3.6 にて AuthenticationMiddleware 試験導入 

CakePHP3.6にてAuthenticationMiddlewareを試してみた結果です。

##インストールは以下サイトを参考に行いました。##
[cakephp/authentication](https://github.com/cakephp/authentication)

##Composerには以下の２つを追加##
* "cakephp/authentication": "^1.0"
* "firebase/php-jwt": "^5.0"

その他に私の設定では php-ldap を追加インストールする必要がありました。

##Application.php  抜粋 ##
```php:Application.php
<?php
namespace App;

use Cake\Http\BaseApplication;
use Cake\Routing\Router;
use Authentication\Middleware\AuthenticationMiddleware;
use Authentication\AuthenticationService;
use Authentication\AuthenticationServiceProviderInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

class Application extends BaseApplication implements AuthenticationServiceProviderInterface
{
    public function getAuthenticationService(ServerRequestInterface $request, ResponseInterface $response)
    {
        $service = new AuthenticationService();
        $service->loadIdentifier('Authentication.Password',
            [
                'fields' => [
                    'username' => 'email',
                    'password' => 'password',
                ],
                'resolver' => [
                    'className' => 'Authentication.Orm',
                    'finder' => 'auth'
                ]
            ]
        );
        $service->loadAuthenticator('Authentication.Session');
        $service->loadAuthenticator('Authentication.Form', [
            'fields' => [
                'username' => 'email',
                'password' => 'password'
            ],
            //'loginUrl' => '/users/login' //指定すると何故かエラー。
            //'loginUrl' => ['controller' => 'users', 'action' => 'login'] //これもエラー
        ]);
        return $service;
    }


    public function bootstrap()
    {
        parent::bootstrap();
        $this->addPlugin('Authentication');
    }

    public function middleware($middlewareQueue)
    {
        $authentication = new AuthenticationMiddleware($this, [
            'unauthenticatedRedirect' =>'/',
            'queryParam' => null,
        ]);
        $middlewareQueue->add($authentication);
        return $middlewareQueue;
    }
}

```
## AppController.php 抜粋 ##

```php:AppController.php
<?php
namespace App\Controller;

use Cake\Controller\Controller;
use Cake\Event\Event;

class AppController extends Controller
{
    public function initialize()
    {
        parent::initialize();
        $this->loadComponent('Security');
        $this->loadComponent('Flash');
        $this->loadComponent('RequestHandler', [
            'enableBeforeRedirect' => false,
        ]);
        $this->loadComponent('Authentication.Authentication', [
            'logoutRedirect' => '/users/login',  // Default is false
            'requireIdentity' => true
        ]);
    }
}
```

## UsersController.php 抜粋  ##
```php:UsersController.php 
<?php

namespace App\Controller;
use Cake\Core\Configure;
use Cake\Event\Event;
use Cake\Http\Exception\InternalErrorException;
use Cake\Mailer\Email;
use Cake\I18n\FrozenTime;
use App\Controller\AppController;
use App\Model\Entity\User;

class UsersController extends AppController
{
    public function beforeFilter(Event $event)
    {
        parent::beforeFilter($event);
        $this->Authentication->allowUnauthenticated(['login', 'add', 'forgot', 'resetPassword', 'confirm']);
    }

    public function login()
    {
        $result = $this->Authentication->getResult();
        if ($result->isValid()) {
            $redirect = $this->request->getQuery('redirect', ['controller' => 'users', 'action' => 'top']);
            return $this->redirect($redirect);
        }
        if ($this->request->is(['post']) && !$result->isValid()) {
            $this->Flash->error(__('User name or password is incorrect'));
        }
    }

    public function top()
    {
        $this->set('user_name', $this->Authentication->getIdentity()->user_name);
    }

    public function logout()
    {
        $this->Authentication->logout();
        $this->Flash->success(__('Logged out.'));
        //設定でリダイレクト先を書いたが動作しないので改めて、ここで指定。
        return $this->redirect(['controller' => 'users', 'action' => 'login']);
    }
}

```

 


## 気になる点 ##

* コンポーネントで logoutRedirect を指定するがリダイレクトしない。
* Authentication.Form にて loginUrl を指定するとエラー。

Chinpeiさん指南のもと以下は克服しました。ありがとうございました。

>chinpei215
>色々聞いてみました。少なくとも一点目の問題は解決しているかもしれません。 requireIdentity は true のままがよさそうです。これがアクションのアクセス可否を制御します。ただし、AuthComponent と違って login も allowUnauthenticated() に列挙する必要があるみたいです。

~~上記設定でログインはできるが、許可していないページも表示されてしまう。~~

## 雑感 ##
* ミドルウエアと共にAuthenticationコンポーネントを入れなくては使えない。
* 設定が多岐に渡り複雑。
* DebagKit も範疇外なので動作確認も不便。（使い方が間違っていだけかも知れません^^;）

結果的にはAuthコンポーネントだけ動作する認証管理の方が簡単かも！？

解釈が違っていたらごめんなさい。
やっぱりミドルウエアの方が良いんだよ〜みたいな意見がありましたら是非お願いします。