关于使用AuthenticationPlugin的Cookie Authenticator实现Remember Me

About the implementation of Remember Me using AuthenticationPlugin's Cookie Authenticator

我使用 CakePHP 的 AuthenticationPlugin。我试图在其中实现 RememberMe 功能。 我在阅读Cakephp文档时发现了以下文章。 Cookie Authenticator aka “Remember Me”

然而,这里的文档对我来说很难理解。我不知道该怎么办。 我已经成功实施了 EncryptedCookieMiddleware。我不知道在那之后该怎么做。 我不知道rememberMeField怎么用,fields怎么用,cookies怎么用。

$this->Authentication->rememberMeField

$this->Authentication->fields

我试了下能不能像这样用,还是不行。 请让我知道如何使用这些。 另外,您知道任何 RememberMe 教程吗? 我该如何实施?

对不起。请帮助我...


// in config/app.php
'Security' => [
        .....
        'cookieKey' => env('SECURITY_COOKIE_KEY', 'AnyString'),  // <- add
    ],
// in src/Application.php
use Cake\Http\Middleware\EncryptedCookieMiddleware; // <- add

  // in middleware()
  public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
    {
      $cookies = new EncryptedCookieMiddleware(  // <- add
            ['mail', 'password'],
            Configure::read('Security.cookieKey')
        );

      $middlewareQueue
        // . . .
        ->add($cookies) // <-add
        ->add(new AuthenticationMiddleware($this));

到目前为止,我已经能够自己实现它。我很自信。 问题出在这之后。我们不知道如何处理它...

在模板表单中实现了记住我复选框。 $this->request->getData('rememberMe');为拿到它,为实现它。 如果这是 1,则复选框已被按下。

// in src/Controller/UsersController
public function login()
    {
        $this->request->allowMethod(['get', 'post']);

        if ($this->request->is('post')) {
            $result = $this->Authentication->getResult();
            //  If the user is logged in, whether POST or GET, we will redirect
            $requestGetData = $this->request->getData('rememberMe');
            if ($requestGetData['rememberMe'] == 1){
                 $this->Authentication->cookie['name'] = $requestGetData['mail'];
                 $this->Authentication->cookie['name'] = $requestGetData['password']
            }
            if ($result->isValid()) {
                $redirect = $this->request->getQuery('redirect', [
                    'controller' => 'Stores',
                    'action'     => 'index',
                ]);

                return $this->redirect($redirect);
            }
            // If the user fails to authenticate after submitting, an error is displayed.
            if (!$result->isValid()) {
                $this->Flash->error(__('Your email address or password is incorrect.'));
            }
        }
        $title = $this->config('Users.title.login');
        $message = $this->config('Users.message.login');
        $this->set(compact('login_now', 'title', 'message'));
    }

我知道那不是真的。但为了以防万一,我试图实现这样的事情。 请帮助我!


围绕登录进行了更改。

public function login()
    {
        $this->request->allowMethod(['get', 'post']);

        if ($this->request->is('post')) {
            $result      = $this->Authentication->getResult();
            $requestData = $this->request->getData();

            if ($result->isValid()) {
                $redirect = $this->request->getQuery('redirect', [
                    'controller' => 'Stores',
                    'action' => 'index',
                ]);
                $this->Authentication->getAuthenticationService()->loadAuthenticator( 'Authentication.Cookie', [
                        'fields' => ['mail', 'password']
                ]
                );
                return $this->redirect($redirect);
            }
            if ($this->request->is('post') && !$result->isValid()) {
                $this->Flash->error(__('Your email address or password is incorrect.'));
            }
        }
        $title = $this->config('Users.title.login');
        $message = $this->config('Users.message.login');
        $this->set(compact('title', 'message'));
    }

你不应该在你的控制器中加载验证器,验证发生在中间件级别,在你的任何控制器被调用之前。

cookie 验证器就像任何其他验证器一样加载和配置,这是您创建验证服务的地方,通常在 src/Application.phpApplication::getAuthenticationService()

默认情况下,表单中的字段必须是 remember_me,而不是 rememberMe,除非您以其他方式配置 cookie 验证器的 rememberMeField 选项。

此外,cookie 验证器的默认 cookie 名称是 CookieAuth,因此如果您想对其进行加密,则必须相应地在 EncryptedCookieMiddleware 配置中使用该名称。

tl;博士

从您的控制器中删除所有与 cookie 相关的代码,并在您的 Application::getAuthenticationService() 方法中加载身份验证器:

use Authentication\Identifier\IdentifierInterface;

// ...

public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface
{
    $service = new AuthenticationService();

    // ...

    // The cookie authenticator should be loaded _after_ the session authenticator,
    // and _before_ other authenticators like the form authenticator
    $service->loadAuthenticator('Authentication.Cookie', [
        // 'rememberMeField' => 'custom_form_field_name', // if you want to change the default
        'fields' => [
            IdentifierInterface::CREDENTIAL_USERNAME => 'mail',
            IdentifierInterface::CREDENTIAL_PASSWORD => 'password',
        ],
    ]);

    // ...

    return $service;
}

EncryptedCookieMiddleware 配置中设置身份验证 cookie 名称:

$cookies = new EncryptedCookieMiddleware(
    ['CookieAuth'],
    Configure::read('Security.cookieKey')
);

并将表单中的字段名称更改为 remember_me 如果您使用的是 cookie 验证器的默认值:

echo $this->Form->control('remember_me', [
    'type' => 'checkbox'
]);

这就是所有需要的,如果您在登录表单中勾选复选框,那么身份验证中间件将在身份验证成功后相应地设置一个 cookie,如果它出现在请求中并且没有其他验证器首先成功验证了请求(例如会话验证器)。