在安全访问控制中使用表达式
另请参阅
处理复杂授权规则的最佳方案是使用 Voter 系统。
除了像 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
,则将授予访问权限(注意:您的 User 对象可能没有 isSuperAdmin()
方法,该方法是为本示例虚构的)。
安全表达式必须使用任何有效的 表达式语言语法,并且可以使用 Symfony 创建的以下任何变量
user
- 表示当前用户的 UserInterface 实例,如果未经验证,则为
null
。 role_names
- 包含用户拥有的角色字符串表示形式的数组。此数组包含通过 角色继承体系 间接授予的任何角色,但不包括
IS_AUTHENTICATED_*
属性(请参阅下面的函数)。 object
- 作为第二个参数传递给
isGranted()
的对象(如果有)。 subject
- 它存储与
object
相同的值,因此它们是等效的。 token
- 令牌对象。
trust_resolver
- AuthenticationTrustResolverInterface 对象:您可能更愿意使用下面的
is_*()
函数。
此外,您可以在表达式内部访问许多函数
is_authenticated()
- 如果用户通过 "remember-me" 验证或 "完全" 验证,则返回
true
- 即,如果用户 "已登录",则返回 true。 is_remember_me()
- 类似于但不等同于
IS_AUTHENTICATED_REMEMBERED
,请参见下文。 is_fully_authenticated()
- 等于检查用户是否具有
IS_AUTHENTICATED_FULLY
角色。 is_granted()
- 检查用户是否具有给定的权限。可以选择接受第二个参数,其中包含要检查权限的对象。它等效于使用安全服务的 isGranted() 方法。
对于 #[IsGranted]
属性,subject 也可以是 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
{
// ...
}
}
在本示例中,我们获取帖子的作者并将其用作 subject。如果 subject 与当前用户匹配,则将授予访问权限。
subject 也可以是一个数组,其中 key 可以用作表达式结果的别名
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
,则将授予访问权限。
您也可以使用当前请求作为 subject
1 2 3 4 5 6 7 8
#[IsGranted(
attribute: '...',
subject: new Expression('request'),
)]
public function index(): Response
{
// ...
}
在 subject 的表达式内部,您可以访问两个变量
request
- 表示当前请求的 Symfony Request 对象。
args
- 传递给控制器的控制器参数数组。
本作品,包括代码示例,根据 Creative Commons BY-SA 3.0 许可获得许可。