Symfony 4.4中如何在@IsGranted注解中使用OR逻辑
Symfony 4.4 实现权限的 OR 逻辑方案
针对你的需求,由于 Symfony 4.4 不支持 @Security 注解,你可以通过以下几种方式实现两个权限的 OR 逻辑:
方法一:控制器内手动检查权限
直接在控制器方法中注入权限检查器,手动判断两个权限是否满足其一:
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; use Symfony\Component\Security\Core\Exception\AccessDeniedException; // 控制器方法 public function yourAction(Module $module, Cm $cm, AuthorizationCheckerInterface $authChecker) { // 检查是否满足任一权限 $hasModulePermission = $authChecker->isGranted(ModulePermission::MODULE_MODERATOR, $module); $hasItemPermission = $authChecker->isGranted(ItemPermission::DELETE_ITEM, $cm); if (!$hasModulePermission && !$hasItemPermission) { throw new AccessDeniedException('无访问权限'); } // 后续业务逻辑 }
方法二:使用 @IsGranted 的 allow_if 参数
Symfony 4.4 的 @IsGranted 注解支持 allow_if 表达式参数,可以直接在注解中编写 OR 逻辑:
use Symfony\Component\Security\Core\Annotation\IsGranted; /** * @IsGranted( * allow_if="is_granted('" . ModulePermission::MODULE_MODERATOR . "', module) or is_granted('" . ItemPermission::DELETE_ITEM . "', cm)" * ) */ public function yourAction(Module $module, Cm $cm) { // 后续业务逻辑 }
注意:需要用字符串拼接引入常量值,确保表达式使用权限的实际字符串标识;同时方法参数名称($module、$cm)要和表达式中的变量名一致。
方法三:自定义权限投票器(Voter)
如果需要在多个控制器复用该逻辑,可以创建自定义 Voter 封装 OR 判断:
- 创建自定义 Voter 类:
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\Voter\Voter; use Symfony\Component\Security\Core\Security; class ModuleOrItemVoter extends Voter { public const MODULE_OR_ITEM_ACCESS = 'MODULE_OR_ITEM_ACCESS'; private $security; public function __construct(Security $security) { $this->security = $security; } protected function supports(string $attribute, $subject): bool { // 只处理自定义权限标识,且subject是包含module和cm的数组 return $attribute === self::MODULE_OR_ITEM_ACCESS && is_array($subject) && isset($subject['module'], $subject['cm']); } protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool { return $this->security->isGranted(ModulePermission::MODULE_MODERATOR, $subject['module']) || $this->security->isGranted(ItemPermission::DELETE_ITEM, $subject['cm']); } }
- 在控制器中使用:
/** * @IsGranted( * ModuleOrItemVoter::MODULE_OR_ITEM_ACCESS, * subject={"module" = "module", "cm" = "cm"} * ) */ public function yourAction(Module $module, Cm $cm) { // 后续业务逻辑 }
内容的提问来源于stack exchange,提问作者Boodyguard
相关产品推荐
相关产品推荐

