Безопасность: Сложный контроль доступа с выражениями
Дата обновления перевода 2024-07-27
Безопасность: Сложный контроль доступа с выражениями
See also
Наилучшим решением для работы со сложными правилами авторизации является использование Системы избирателей.
В дополнение к роли вроде ROLE_ADMIN
, метод 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
-
Экземпляр UserInterface,
который представляет текущего пользователя или
null
, если вы не аутентифицированы. 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
- Массив аргументов контроллера, которые передаются контроллеру.