使用 composer 从 CakePHP 项目的根目录(composer.json 文件所在位置)安装插件。
php composer.phar require cakephp/authentication
身份验证插件的版本 3 与 CakePHP 5 兼容。
通过在项目的 src/Application.php
中添加以下语句来加载插件
public function bootstrap(): void
{
parent::bootstrap();
$this->addPlugin('Authentication');
}
身份验证插件作为 中间件 与您的应用程序集成。 它也可以用作组件,使未经身份验证的访问更加简单。 首先,让我们应用中间件。 在 src/Application.php 中,将以下内容添加到类导入中
use Authentication\AuthenticationService;
use Authentication\AuthenticationServiceInterface;
use Authentication\AuthenticationServiceProviderInterface;
use Authentication\Identifier\AbstractIdentifier;
use Authentication\Identifier\IdentifierInterface;
use Authentication\Middleware\AuthenticationMiddleware;
use Cake\Http\MiddlewareQueue;
use Cake\Routing\Router;
use Psr\Http\Message\ServerRequestInterface;
接下来,将 AuthenticationServiceProviderInterface
添加到应用程序的实现接口上
class Application extends BaseApplication implements AuthenticationServiceProviderInterface
然后更新应用程序的 middleware()
方法,使其看起来像
public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
{
$middlewareQueue->add(new ErrorHandlerMiddleware(Configure::read('Error')))
// Other middleware that CakePHP provides.
->add(new AssetMiddleware())
->add(new RoutingMiddleware($this))
->add(new BodyParserMiddleware())
// Add the AuthenticationMiddleware. It should be
// after routing and body parser.
->add(new AuthenticationMiddleware($this));
return $middlewareQueue;
}
警告
中间件的顺序很重要。 确保将 AuthenticationMiddleware
放在路由和主体解析器中间件之后。 如果您在使用 JSON 请求登录或重定向不正确时遇到问题,请仔细检查中间件顺序。
AuthenticationMiddleware
在开始处理请求时将在您的应用程序上调用一个钩子方法。 此钩子方法允许您的应用程序定义要使用的 AuthenticationService
。 将以下方法添加到 src/Application.php
/**
* Returns a service provider instance.
*
* @param \Psr\Http\Message\ServerRequestInterface $request Request
* @return \Authentication\AuthenticationServiceInterface
*/
public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface
{
$service = new AuthenticationService();
// Define where users should be redirected to when they are not authenticated
$service->setConfig([
'unauthenticatedRedirect' => Router::url([
'prefix' => false,
'plugin' => null,
'controller' => 'Users',
'action' => 'login',
]),
'queryParam' => 'redirect',
]);
$fields = [
AbstractIdentifier::CREDENTIAL_USERNAME => 'email',
AbstractIdentifier::CREDENTIAL_PASSWORD => 'password'
];
// Load the authenticators. Session should be first.
$service->loadAuthenticator('Authentication.Session');
$service->loadAuthenticator('Authentication.Form', [
'fields' => $fields,
'loginUrl' => Router::url([
'prefix' => false,
'plugin' => null,
'controller' => 'Users',
'action' => 'login',
]),
]);
// Load identifiers
$service->loadIdentifier('Authentication.Password', compact('fields'));
return $service;
}
首先,我们配置在用户未经身份验证时该怎么做。 接下来,我们附加 Session
和 Form
身份验证器,它们定义了应用程序将用于对用户进行身份验证的机制。 Session
使我们能够根据会话中的数据来识别用户,而 Form
使我们能够在 loginUrl
上处理登录表单。 最后,我们附加一个 标识符 将用户提供的凭据转换为一个 身份,它代表已登录的用户。
如果配置的身份验证器之一能够验证凭据,则中间件将身份验证服务作为 属性 添加到请求对象中。
接下来,在您的 AppController
中加载 身份验证组件
// in src/Controller/AppController.php
public function initialize()
{
parent::initialize();
$this->loadComponent('Authentication.Authentication');
}
默认情况下,组件将要求对 所有 操作进行身份验证。 您可以使用 allowUnauthenticated()
在特定控制器中禁用此行为
// in a controller beforeFilter or initialize
// Make view and index not require a logged in user.
$this->Authentication->allowUnauthenticated(['view', 'index']);
将中间件应用于应用程序后,您将需要一种方法让用户登录。 请确保您的数据库已使用 教程 中使用的 Users 表结构创建。 首先使用 bake 生成 Users 模型和控制器
bin/cake bake model Users
bin/cake bake controller Users
然后,我们将向您的 UsersController
添加一个基本的登录操作。 它应该看起来像
// in src/Controller/UsersController.php
public function login()
{
$result = $this->Authentication->getResult();
// If the user is logged in send them away.
if ($result->isValid()) {
$target = $this->Authentication->getLoginRedirect() ?? '/home';
return $this->redirect($target);
}
if ($this->request->is('post')) {
$this->Flash->error('Invalid username or password');
}
}
确保您允许访问控制器 beforeFilter()
回调中的 login
操作,如上一节所述,以便未经身份验证的用户能够访问它
// in src/Controller/UsersController.php
public function beforeFilter(\Cake\Event\EventInterface $event)
{
parent::beforeFilter($event);
$this->Authentication->allowUnauthenticated(['login']);
}
接下来,我们将为登录表单添加一个视图模板
// in templates/Users/login.php
<div class="users form content">
<?= $this->Form->create() ?>
<fieldset>
<legend><?= __('Please enter your email and password') ?></legend>
<?= $this->Form->control('email') ?>
<?= $this->Form->control('password') ?>
</fieldset>
<?= $this->Form->button(__('Login')); ?>
<?= $this->Form->end() ?>
</div>
然后添加一个简单的注销操作
// in src/Controller/UsersController.php
public function logout()
{
$this->Authentication->logout();
return $this->redirect(['controller' => 'Users', 'action' => 'login']);
}
我们不需要注销操作的模板,因为我们在最后重定向。
为了登录您的用户,他们将需要使用哈希密码。 您可以使用实体 setter 方法在用户更新其密码时自动哈希密码
// in src/Model/Entity/User.php
use Authentication\PasswordHasher\DefaultPasswordHasher;
class User extends Entity
{
// ... other methods
// Automatically hash passwords when they are changed.
protected function _setPassword(string $password)
{
$hasher = new DefaultPasswordHasher();
return $hasher->hash($password);
}
}
现在,您应该能够转到 /users/add
并注册一个新用户。 注册后,您可以转到 /users/login
并使用您新创建的用户登录。