Spring Security 6.x中AccessDecisionVoter弃用,如何用AuthorizationManager实现角色层级?
完全可以通过AuthorizationManager体系实现角色层级配置,替代原有的RoleHierarchyVoter。Spring Security 6.x(对应Spring Boot 3.x)用AuthorizationManager替代了旧的投票器体系,结合RoleHierarchy和RoleHierarchyAuthoritiesMapper就能实现相同的角色层级效果。
具体配置步骤
保留RoleHierarchy Bean配置
这部分和Spring Boot 2.7.x的配置基本一致,用于定义角色的层级关系:@Bean public RoleHierarchy roleHierarchy() { RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl(); roleHierarchy.setHierarchy("ROLE_ADMINISTRATOR > ROLE_USER > ROLE_GUEST"); return roleHierarchy; }配置RoleHierarchyAuthoritiesMapper
这个Mapper会根据你定义的角色层级,自动扩展用户的权限集合(比如拥有ROLE_ADMINISTRATOR的用户会自动获得ROLE_USER和ROLE_GUEST的权限):@Bean public AuthoritiesMapper authoritiesMapper(RoleHierarchy roleHierarchy) { return new RoleHierarchyAuthoritiesMapper(roleHierarchy); }创建带层级支持的AuthorizationManager
使用AuthorityAuthorizationManager并注入上面的AuthoritiesMapper,让权限判断时自动应用角色层级:@Bean public AuthorizationManager<RequestAuthorizationContext> authorizationManager(AuthoritiesMapper authoritiesMapper) { // 这里可以根据需求设置需要的角色,比如要求用户拥有USER及以上角色 AuthorityAuthorizationManager<RequestAuthorizationContext> authManager = AuthorityAuthorizationManager.hasAnyRole("USER", "ADMINISTRATOR"); authManager.setAuthoritiesMapper(authoritiesMapper); return authManager; }在SecurityFilterChain中应用AuthorizationManager
将配置好的AuthorizationManager绑定到请求授权规则中:@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http, AuthorizationManager<RequestAuthorizationContext> authorizationManager) throws Exception { http .authorizeHttpRequests(auth -> auth .anyRequest().access(authorizationManager) // 也可以针对特定路径单独配置,比如: // .requestMatchers("/admin/**").access(AuthorityAuthorizationManager.hasRole("ADMINISTRATOR").setAuthoritiesMapper(authoritiesMapper)) // .requestMatchers("/user/**").access(AuthorityAuthorizationManager.hasRole("USER").setAuthoritiesMapper(authoritiesMapper)) ); return http.build(); }
原理说明
RoleHierarchyAuthoritiesMapper会在权限判断前,将用户的直接角色扩展为包含所有继承角色的完整权限列表,这样AuthorizationManager在校验权限时,就能识别到层级关系带来的隐含权限,和原来RoleHierarchyVoter的作用逻辑一致,但适配了Spring Security 6.x的新授权体系。
内容的提问来源于stack exchange,提问作者Peter Andres

