如何使用Spring新配置API配置@Secured注解与RoleHierarchy?
问题原因与解决方案
问题根源在于:@Secured注解的权限校验由RoleVoter负责,但默认的RoleVoter不会自动应用RoleHierarchy定义的角色继承关系。你之前的旧配置通过自定义AccessDecisionManager整合了相关逻辑,但新的@EnableMethodSecurity模式下,需要显式配置支持角色层级的投票器。
正确配置方式
方式一:继承GlobalMethodSecurityConfiguration重写关键方法
@Configuration @EnableMethodSecurity(securedEnabled = true) public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration { private final RoleHierarchy roleHierarchy; public MethodSecurityConfig(RoleHierarchy roleHierarchy) { this.roleHierarchy = roleHierarchy; } @Override protected AccessDecisionManager accessDecisionManager() { // 使用支持角色层级的RoleHierarchyVoter替代默认RoleVoter RoleHierarchyVoter roleHierarchyVoter = new RoleHierarchyVoter(roleHierarchy); // 组装必要的投票器列表 List<AccessDecisionVoter<?>> voters = List.of( roleHierarchyVoter, new AuthenticatedVoter(), new Jsr250Voter() ); return new AffirmativeBased(voters); } @Override protected MethodSecurityExpressionHandler createExpressionHandler() { // 确保表达式注解(如@PreAuthorize)也支持角色层级 DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler(); handler.setRoleHierarchy(roleHierarchy); return handler; } }
方式二:直接配置Bean(无需继承父类)
@Configuration @EnableMethodSecurity(securedEnabled = true) public class MethodSecurityConfig { @Bean AccessDecisionManager accessDecisionManager(RoleHierarchy roleHierarchy) { RoleHierarchyVoter roleHierarchyVoter = new RoleHierarchyVoter(roleHierarchy); List<AccessDecisionVoter<?>> voters = List.of( roleHierarchyVoter, new AuthenticatedVoter(), new Jsr250Voter() ); return new AffirmativeBased(voters); } @Bean MethodSecurityExpressionHandler methodSecurityExpressionHandler(RoleHierarchy roleHierarchy) { DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler(); handler.setRoleHierarchy(roleHierarchy); return handler; } }
关键说明
RoleHierarchyVoter是Spring提供的专门处理角色层级的投票器,它会利用传入的RoleHierarchy解析角色继承关系,确保@Secured注解能识别父角色的权限。- 配置
MethodSecurityExpressionHandler是为了让@PreAuthorize、@PostAuthorize等表达式型注解也支持角色层级,如果你只需要@Secured生效,这一步可以保留(不影响),也可以根据需求调整。
内容的提问来源于stack exchange,提问作者hurelhuyag
相关产品推荐
相关产品推荐

