Spring6/SpringBoot3自定义PermissionEvaluator未生效,始终用DenyAllPermissionEvaluator
排查与解决自定义PermissionEvaluator未生效问题
1. 确认@EnableMethodSecurity的配置有效性
Spring Security 6中@EnableMethodSecurity默认启用prePostEnabled=true(支持@PreAuthorize/@PostAuthorize),但如果显式配置错误参数会导致注解失效。确保安全配置类上的注解未禁用prePost支持:
// 正确示例,默认已开启prePost支持,无需额外参数 @Configuration @EnableMethodSecurity public class SecurityConfig { // ... 其他安全配置 }
2. 按Spring 6规范注册自定义PermissionEvaluator
Spring 6不再推荐通过GlobalMethodSecurityConfiguration重写表达式处理器,需通过实现MethodSecurityConfigurer来绑定自定义PermissionEvaluator:
步骤1:确保自定义PermissionEvaluator为Spring Bean
@Component public class CustomPermissionEvaluator implements PermissionEvaluator { @Override public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) { // 你的权限校验逻辑 System.out.println("自定义PermissionEvaluator已触发"); return true; } @Override public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) { // 按需实现ID+类型的权限校验逻辑 return true; } }
步骤2:绑定表达式处理器与自定义PermissionEvaluator
创建专门的方法安全配置类,将自定义校验器注入到表达式处理器:
@Configuration @EnableMethodSecurity public class MethodSecurityConfig implements MethodSecurityConfigurer<MethodSecurityExpressionHandler, MethodSecurityConfiguration> { private final CustomPermissionEvaluator customPermissionEvaluator; // 构造注入自定义校验器 public MethodSecurityConfig(CustomPermissionEvaluator customPermissionEvaluator) { this.customPermissionEvaluator = customPermissionEvaluator; } @Override public void configure(MethodSecurityConfiguration config) throws Exception { DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler(); expressionHandler.setPermissionEvaluator(customPermissionEvaluator); // 将自定义表达式处理器绑定到方法安全配置 config.setMethodSecurityExpressionHandler(expressionHandler); } }
3. 检查@PreAuthorize表达式的正确性
确保接口上的@PreAuthorize使用hasPermission()表达式,否则不会触发PermissionEvaluator:
@RestController @RequestMapping("/api/resources") public class ResourceController { // 正确示例:用hasPermission触发自定义校验 @PreAuthorize("hasPermission(#resourceId, 'Resource', 'read')") @GetMapping("/{resourceId}") public ResponseEntity<String> getResource(@PathVariable Long resourceId) { return ResponseEntity.ok("访问成功"); } }
注意:表达式参数需与PermissionEvaluator的方法参数对应,比如#resourceId对应targetId,'Resource'对应targetType,'read'对应permission。
4. 排查Bean冲突问题
如果存在多个PermissionEvaluator类型的Bean,Spring可能默认选择DenyAllPermissionEvaluator。解决方式:
- 确保自定义PermissionEvaluator是唯一的该类型Bean
- 给自定义Bean添加
@Primary注解,强制Spring优先使用:
@Component @Primary public class CustomPermissionEvaluator implements PermissionEvaluator { // ... 实现代码 }
5. 验证Authentication对象有效性
JWT认证成功后,确保生成的Authentication对象被正确传递到方法安全校验流程。可在自定义PermissionEvaluator的方法中打印authentication对象,确认其不为空且包含正确用户信息。
内容的提问来源于stack exchange,提问作者Sai prateek
相关产品推荐
相关产品推荐

