Encodera

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

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

Оглавление

Права доступа

Аутентификация отвечает на вопрос «кто это», а права доступа — «что ему можно». Самая частая задача — не пускать гостей на страницы добавления и удаления статей. Проверять это в каждом действии неудобно, поэтому проверку ставят в одно место, через которое проходит любой запрос.

Где ставить проверку

У класса модуля есть метод onBootstrap(): Laminas вызывает его при запуске. В нём можно подписаться на событие — шаг обработки запроса. Событие MvcEvent::EVENT_ROUTE происходит, когда маршрут уже определён, а контроллер ещё не вызван. Подробнее о событиях рассказывает отдельный урок.

Закрытые маршруты

Откройте module/Blog/src/Module.php и добавьте метод (если он уже есть после урока о сессиях — допишите в него):

// module/Blog/src/Module.php
use Laminas\Authentication\AuthenticationService;
use Laminas\Mvc\MvcEvent;
 
public function onBootstrap(MvcEvent $event): void
{
    $events = $event->getApplication()->getEventManager();
 
    $events->attach(MvcEvent::EVENT_ROUTE, function (MvcEvent $e) {
        $match = $e->getRouteMatch();
 
        if ($match === null) {
            return;
        }
 
        $protected = ['blog/add', 'blog/edit', 'blog/delete'];
        $auth = $e->getApplication()->getServiceManager()->get(AuthenticationService::class);
 
        if (!in_array($match->getMatchedRouteName(), $protected, true) || $auth->hasIdentity()) {
            return;
        }
 
        $response = $e->getResponse();
        $response->getHeaders()->addHeaderLine('Location', $e->getRouter()->assemble([], ['name' => 'login']));
        $response->setStatusCode(302);
 
        return $response;
    }, -100);
}

Слушатель берёт имя сработавшего маршрута. Если оно в списке закрытых, а посетитель не вошёл, слушатель возвращает ответ с перенаправлением, и контроллер не вызывается. Число -100 — приоритет: отрицательное значение ставит слушателя после встроенного определения маршрута.

Выйдите через /logout и откройте /blog/add — браузер окажется на /login.

Роли и разрешения

Когда пользователей несколько видов, одного «вошёл или нет» мало. Пакет laminas-permissions-acl описывает список прав (ACL): роли, ресурсы и разрешения.

composer require laminas/laminas-permissions-acl
use Laminas\Permissions\Acl\Acl;
 
$acl = new Acl();
 
$acl->addRole('guest');
$acl->addRole('editor', 'guest');
$acl->addRole('admin', 'editor');
 
$acl->addResource('post');
 
$acl->allow('guest', 'post', 'view');
$acl->allow('editor', 'post', ['add', 'edit']);
$acl->allow('admin');
 
$acl->isAllowed('editor', 'post', 'edit');   // true
$acl->isAllowed('editor', 'post', 'delete'); // false

Второй аргумент addRole() — родитель: editor может всё, что может guest. Вызов allow('admin') без ресурса разрешает роли всё.

ПонятиеЧто этоПример
РольВид пользователяguest, editor, admin
РесурсТо, к чему ограничен доступpost
ПривилегияДействие над ресурсомview, edit, delete

Объект Acl создают в фабрике и регистрируют как сервис, а в слушателе вместо hasIdentity() вызывают isAllowed() с ролью из личности пользователя. Для больших проектов есть похожий пакет laminas-permissions-rbac, где права привязаны к ролям без ресурсов.

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

Скрыть ссылку «Удалить» в шаблоне — не защита: адрес /blog/delete/5 можно набрать вручную. Права проверяют на сервере — в слушателе или в действии, — а скрытие ссылок только делает страницу удобнее.

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

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