Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Вход на сайт

Аутентификация — проверка того, кто перед нами: посетитель вводит почту и пароль, сайт запоминает его в сессии. В CakePHP этим занимается официальный плагин Authentication. Плагин — отдельный пакет, расширяющий фреймворк.

Установка

composer require "cakephp/authentication:^3.0"
bin/cake plugin load Authentication

Первая команда скачивает пакет, вторая включает его в проекте.

Таблица пользователей

bin/cake bake migration CreateUsers email:string:unique password:string created modified
bin/cake migrations migrate
bin/cake bake all Users

Появятся таблица users, модель, контроллер UsersController и шаблоны — в том числе форма регистрации /users/add.

Хеш пароля

Пароль нельзя хранить открытым текстом. Добавьте в класс записи метод, который хеширует его при каждом присваивании:

// src/Model/Entity/User.php
use Authentication\PasswordHasher\DefaultPasswordHasher;
 
protected function _setPassword(string $password): ?string
{
    return $password !== '' ? (new DefaultPasswordHasher())->hash($password) : null;
}

Метод с приставкой _set вызывается при записи в поле. Зарегистрируйте пользователя на /users/add — в базе окажется длинная строка хеша.

Настройка

Плагин настраивают в src/Application.php. Класс должен реализовать интерфейс и получить новый метод:

// src/Application.php
use Authentication\AuthenticationService;
use Authentication\AuthenticationServiceInterface;
use Authentication\AuthenticationServiceProviderInterface;
use Authentication\Middleware\AuthenticationMiddleware;
use Psr\Http\Message\ServerRequestInterface;
 
class Application extends BaseApplication implements AuthenticationServiceProviderInterface
{
    public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface
    {
        $service = new AuthenticationService([
            'unauthenticatedRedirect' => '/users/login',
            'queryParam' => 'redirect',
        ]);
 
        $fields = ['username' => 'email', 'password' => 'password'];
 
        $service->loadAuthenticator('Authentication.Session');
        $service->loadAuthenticator('Authentication.Form', [
            'fields' => $fields,
            'loginUrl' => '/users/login',
        ]);
        $service->loadIdentifier('Authentication.Password', ['fields' => $fields]);
 
        return $service;
    }
}

Session узнаёт уже вошедшего пользователя, Form проверяет отправленную форму входа. В методе middleware() того же файла добавьте строку после RoutingMiddleware:

->add(new AuthenticationMiddleware($this))

И подключите компонент в AppController::initialize():

$this->loadComponent('Authentication.Authentication');

С этого момента все страницы требуют входа: гостя перенаправляет на /users/login.

Вход и выход

// src/Controller/UsersController.php
public function beforeFilter(\Cake\Event\EventInterface $event): void
{
    parent::beforeFilter($event);
 
    $this->Authentication->allowUnauthenticated(['login', 'add']);
}
 
public function login()
{
    $result = $this->Authentication->getResult();
 
    if ($result && $result->isValid()) {
        return $this->redirect($this->Authentication->getLoginRedirect() ?? '/');
    }
 
    if ($this->request->is('post')) {
        $this->Flash->error('Неверная почта или пароль.');
    }
}
 
public function logout()
{
    $this->Authentication->logout();
 
    return $this->redirect(['action' => 'login']);
}

Почту и пароль проверяет сам плагин — действию остаётся посмотреть на результат. allowUnauthenticated() открывает перечисленные действия гостям.

Форма входа

Создайте templates/Users/login.php:

<h1>Вход</h1>
 
<?= $this->Form->create() ?>
<?= $this->Form->control('email', ['label' => 'Почта']) ?>
<?= $this->Form->control('password', ['label' => 'Пароль']) ?>
<?= $this->Form->button('Войти') ?>
<?= $this->Form->end() ?>

Откройте /articles — вас перенаправит на форму входа, а после входа вернёт обратно.

Текущий пользователь

$user = $this->request->getAttribute('identity');
 
$userId = $user->getIdentifier();
$email = $user->email;

Атрибут identity содержит вошедшего пользователя или null для гостя.

Частая ошибка

После подключения плагина закрытыми становятся все страницы, включая саму страницу входа. Если не открыть её через allowUnauthenticated(['login']), гость попадёт в бесконечное перенаправление. Публичные страницы — список и просмотр статей — открывают так же в beforeFilter() своего контроллера.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.