Авторизация: фильтр AccessControl
Авторизация отвечает на вопрос «что этому пользователю разрешено». Аутентификация выяснила, кто вошёл; теперь нужно решить, можно ли ему создавать и менять статьи. Самый простой инструмент — фильтр AccessControl, который проверяет доступ до выполнения действия.
Где подключают фильтр
Фильтр подключают в методе behaviors() контроллера. Добавьте в controllers/PostController.php:
// controllers/PostController.php
use yii\filters\AccessControl;
public function behaviors(): array
{
return [
'access' => [
'class' => AccessControl::class,
'only' => ['create', 'update', 'delete'],
'rules' => [
[
'allow' => true,
'roles' => ['@'],
],
],
],
];
}Выйдите с сайта и откройте /post/create — Yii перенаправит на страницу входа, а после входа вернёт обратно. Список и просмотр статей остаются открытыми: only перечисляет действия, к которым применяется фильтр.
Как читаются правила
Правила проверяются сверху вниз, срабатывает первое подходящее. Если не подошло ни одно, доступ запрещён.
| Ключ правила | Значение |
|---|---|
allow | true — разрешить, false — запретить |
roles | @ — вошедший пользователь, ? — гость, либо имя роли |
actions | Действия, к которым относится правило |
verbs | Методы запроса, например ['POST'] |
ips | Адреса посетителей |
Разные правила для разных действий
'rules' => [
[
'allow' => true,
'actions' => ['index', 'view'],
'roles' => ['?', '@'],
],
[
'allow' => true,
'actions' => ['create', 'update', 'delete'],
'roles' => ['@'],
],
],Без ключа only фильтр действует на все действия контроллера: читать статьи могут все, менять — только вошедшие. Действие, не упомянутое ни в одном правиле, закрыто для всех.
Что видит посетитель
Гостя Yii перенаправляет на адрес входа. Его задаёт свойство компонента user в config/web.php:
// config/web.php
'user' => [
'identityClass' => 'app\models\User',
'loginUrl' => ['site/login'],
],Вошедший пользователь, которому доступ запрещён, получает ошибку 403 «Forbidden».
Проверка владельца
Фильтр не знает, чью статью открывают. Что менять статью может только её автор, проверяют в самом действии:
use yii\web\ForbiddenHttpException;
public function actionUpdate(int $id)
{
$post = Post::findOne($id);
if ($post === null) {
throw new NotFoundHttpException('Статья не найдена.');
}
if ($post->user_id !== Yii::$app->user->id) {
throw new ForbiddenHttpException('Это не ваша статья.');
}
// загрузка формы и сохранение
}Чужую статью по адресу /post/update?id=7 изменить не получится: страница ответит ошибкой 403.
Ссылки в шаблоне
Кнопки, которыми посетитель не может воспользоваться, скрывают:
<?php
// views/post/view.php
use yii\helpers\Html;
?>
<?php if (!Yii::$app->user->isGuest && $post->user_id === Yii::$app->user->id): ?>
<?= Html::a('Изменить', ['post/update', 'id' => $post->id]) ?>
<?php endif; ?>Ссылку «Изменить» увидит только автор статьи.
Частая ошибка
Скрыть ссылку в шаблоне — не значит закрыть доступ. Адрес /post/update?id=7 можно набрать вручную, и без проверки в контроллере действие выполнится. Шаблон управляет удобством, а права проверяют фильтр и код действия.