Symfony同一控制器多IsGranted注解不生效问题求解
问题原因
你遇到的问题是因为方法上的多个IsGranted注解默认是逻辑与(AND)关系:访问任意一个路由时,所有注解的权限检查都会执行。当访问app_admin_restock_announcement_create路由时,$restockQueue为null,第二个IsGranted(RestockVoter::EDIT_RESTOCK, 'restockQueue')会尝试用null作为校验主体(subject)进行检查。如果你的Voter中EDIT_RESTOCK逻辑要求主体必须是有效的RestockQueue实例,这一步会返回权限失败,最终导致整体校验不通过——哪怕第一个CREATE_RESTOCK的检查返回true。
解决方案:给
IsGranted添加路由条件 通过给每个IsGranted注解添加condition参数,让权限检查仅在对应路由下生效,两个路由的权限校验就不会互相干扰:
#[Route('/announcement/create', name: 'app_admin_restock_announcement_create')] #[IsGranted(RestockVoter::CREATE_RESTOCK, condition: "request.attributes.get('_route') == 'app_admin_restock_announcement_create'")] #[Route('/announcement/edit/{id}', name: 'app_admin_restock_announcement_edit')] #[IsGranted(RestockVoter::EDIT_RESTOCK, 'restockQueue', condition: "request.attributes.get('_route') == 'app_admin_restock_announcement_edit'")] public function detail( ?RestockQueue $restockQueue, // ... 其他参数 ) { // ... 控制器逻辑 }
原理说明
condition参数使用Symfony表达式语言,通过request.attributes.get('_route')获取当前访问的路由名称,只有路由匹配时,对应的IsGranted检查才会执行。- 访问
create路由时,仅校验CREATE_RESTOCK权限;访问edit路由时,仅校验EDIT_RESTOCK权限(此时restockQueue已通过参数转换器正确加载)。
这样无需拆分控制器,纯通过注解就能实现分路由的权限控制。
内容的提问来源于stack exchange,提问作者Talha Amir
相关产品推荐
相关产品推荐

