Використання виразів у контролі доступу безпеки
Дата оновлення перекладу 2025-09-15
Використання виразів у контролі доступу безпеки
See also
Найкращим рішенням для роботи зі складними правилами авторизації є використання Системи виборців.
На додаток до ролі типу ROLE_ADMIN, метод isGranted() та атрибут
#[IsGranted] також приймають обʼєкт
Expression:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// src/Controller/MyController.php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\ExpressionLanguage\Expression;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Http\Attribute\IsGranted;
class MyController extends AbstractController
{
#[IsGranted(new Expression('is_granted("ROLE_ADMIN") or is_granted("ROLE_MANAGER")'))]
public function show(): Response
{
// ...
}
#[IsGranted(new Expression(
'"ROLE_ADMIN" in role_names or (is_authenticated() and user.isSuperAdmin())'
))]
public function edit(): Response
{
// ...
}
}
У цьому прикладі, якщо поточний користувач має ROLE_ADMIN або якщо метод обʼєкта
поточного користувача isSuperAdmin() повертає true, то доступ буде гарантовано
(примітка: ваш обʼєкт Користувача може не мати методу isSuperAdmin(), цей метод
було вигадано для цього прикладу).
Вираз безпеки повинен використовувати будь-який валідний синтаксис мови виразів і може використовувати будь-яку з цих змінних, створених Symfony:
user-
Обʼєкт користувача (або рядок
anon, якщо ви не аутентифіковані). role_names-
Масив ролей, які має користувач, з рядковим представленням. Цей масив включає в себе
всі ролі надані не напряму через ієрархію ролей , але
не включає атрибути
IS_AUTHENTICATED_*(див. функції нижче). object-
Обʼєкт (якщо є), який передається в якості другого аргументу
isGranted(). subject-
Зберігає те ж значення, що і
object, тому вони еквівалентні. token- Обʼєкт токена.
trust_resolver-
Обʼєкт AuthenticationTrustResolverInterface,:
ви скоріш за все використовуватимете функції
is_*(), описані нижче.
Крім того, у вас є доступ до наступних функцій всередині виразу:
is_authenticated()-
Повертає
true, якщо користувач аутентифікований через "запамʼятати мене" або "повністю" аутентифікований - тобто, повертає "true", якщо користувач знаходиться у системі. is_remember_me()-
Схоже, але не еквівалентно з
IS_AUTHENTICATED_REMEMBERED, див. нижче. is_fully_authenticated()-
Схоже, але не евівалентно з
IS_AUTHENTICATED_FULLY, див. нижче. is_granted()- Перевіряє, чи є у користувача заданий дозвіл. Додатково приймає другий аргумент з обʼєктом, де перевіряється дозвіл. Еквівалентно використанню методу isGranted() з сервісу безпеки.
У випадку атрибуту #[IsGranted()] суб'єктом також може бути об'єкт
Expression:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
// src/Controller/MyController.php
namespace App\Controller;
use App\Entity\Post;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\ExpressionLanguage\Expression;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Http\Attribute\IsGranted;
class MyController extends AbstractController
{
#[IsGranted(
attribute: new Expression('user === subject'),
subject: new Expression('args["post"].getAuthor()'),
)]
public function index(Post $post): Response
{
// ...
}
}
У цьому прикладі ми отримуємо автора посту і використовуємо його як субʼєкт. Якщо субʼєкт збігається з поточним користувачем, то доступ буде надано.
Субʼєкт також може бути масивом, де ключ можна використовувати як псевдонім для результату виразу:
1 2 3 4 5 6 7 8 9 10 11
#[IsGranted(
attribute: new Expression('user === subject["author"] and subject["post"].isPublished()'),
subject: [
'author' => new Expression('args["post"].getAuthor()'),
'post',
],
)]
public function index(Post $post): Response
{
// ...
}
Тут доступ буде надано, якщо автор збігається з поточним користувачем
і метод посту isPublished() повертає true.
Ви також можете використовувати поточний запит як субʼєк:
1 2 3 4 5 6 7 8
#[IsGranted(
attribute: '...',
subject: new Expression('request'),
)]
public function index(): Response
{
// ...
}
Всередині виразу субʼєкта ви маєте доступ до двох змінних:
request- Об'єкт Symfony Request , який представляє поточний запит.
args- Масив аргументів контролера, які передаються контролеру.
Окрім виразів, атрибут #[IsGranted] також приймає замикання, які повертають
булеве значення. Субʼєкт також може бути замиканням, яке повертає масив значень,
що будуть впроваджені у замикання:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
// src/Controller/MyController.php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Http\Attribute\IsGranted;
use Symfony\Component\Security\Http\Attribute\IsGrantedContext;
class MyController extends AbstractController
{
#[IsGranted(static function (IsGrantedContext $context, mixed $subject) {
return $context->user === $subject['post']->getAuthor();
}, subject: static function (array $args) {
return [
'post' => $args['post'],
];
})]
public function index($post): Response
{
// ...
}
}
7.3
Підтримка замикань в атрибуті #[IsGranted] була представлена в
Symfony 7.3 і вимагає PHP 8.5.