Spring Security角色层次结构@Secured JavaConfig

Spring Security角色层次结构@Secured JavaConfig

问题描述:

我遇到了一些问题,试图在Spring Security中使用JavaConfig而不是XML实现角色层次结构。有没有办法用@Secured注解而不是HttpSecurity antMatchers实现角色层次结构?我似乎无法将角色层次结构添加到HttpSecurity中,但没有提供正确的String模式,尽管我希望能够仅使用@Secured做出访问决策。Spring Security角色层次结构@Secured JavaConfig

java.lang.IllegalStateException: At least one mapping is required (i.e. authorizeRequests().anyRequest.authenticated()) 

@Bean 
public RoleHierarchyImpl roleHierarchy() { 
    RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl(); 
    roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER"); 
    return roleHierarchy; 
} 

private SecurityExpressionHandler<FilterInvocation> webExpressionHandler() { 
    DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler(); 
    defaultWebSecurityExpressionHandler.setRoleHierarchy(roleHierarchy()); 
    return defaultWebSecurityExpressionHandler; 
} 

public void configure(HttpSecurity http){ 
http.authorizeRequests().expressionHandler(webExpressionHandler()).and().//other stuff 
} 

对此非常感谢。

+0

你的RoleHierarchyImpl是什么样的? – Stefan

+0

编辑我的文章。大部分使用http://*.com/questions/29888458/spring-security-role-hierarchy-not-working-using-java-config,但有什么办法可以摆脱antMatchers,因为我只是想使用@Secured注释 – Lukehey

我也希望有一个使用@Secured注释的角色层次结构。发现它非常棘手,但最终有一个以下的解决方案(groovy代码)。

定义你的选民和决定经理@Configuration类:

@Bean 
    public static RoleHierarchy roleHierarchy() { 
    RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl() 
    roleHierarchy.setHierarchy("""\ 
     $SUPER_ADMIN > $ORGANIZATION_ADMIN 
     $ORGANIZATION_ADMIN > $DOCTOR 
     $DOCTOR > $NURSE 
     $NURSE > $PATIENT 
     $PATIENT > $USER""".stripIndent()) 
    roleHierarchy 
    } 

    @Bean 
    public static RoleHierarchyVoter roleVoter() { 
    new RoleHierarchyVoter(roleHierarchy()) 
    } 

    @Bean 
    public AffirmativeBased accessDecisionManager() { 
    List<AccessDecisionVoter> decisionVoters = new ArrayList<>(); 
    decisionVoters.add(webExpressionVoter()); 
    decisionVoters.add(roleVoter()); 
    new AffirmativeBased(decisionVoters); 
    } 

    private WebExpressionVoter webExpressionVoter() { 
    WebExpressionVoter webExpressionVoter = new WebExpressionVoter() 
    webExpressionVoter.setExpressionHandler(expressionHandler()) 
    webExpressionVoter 
    } 

    @Bean 
    public DefaultWebSecurityExpressionHandler expressionHandler(){ 
    DefaultWebSecurityExpressionHandler expressionHandler = new DefaultWebSecurityExpressionHandler(); 
    expressionHandler.setRoleHierarchy(roleHierarchy()); 
    return expressionHandler; 
    } 

然后在安全性配置中添加的决策管理器:

@Override 
    protected void configure(HttpSecurity http) throws Exception { 
    http 
     ... 
     .and() 
     .authorizeRequests() 
     .accessDecisionManager(accessDecisionManager()) 
     .antMatchers("/auth").permitAll() 
     ... 
    } 

然后,你还必须覆盖GlobalMethodSecurityConfiguration也使用RoleHierarchyVoter:

@Configuration 
@EnableGlobalMethodSecurity(securedEnabled = true) 
class MethodSecurityConfiguration extends GlobalMethodSecurityConfiguration { 

    @Override 
    protected MethodSecurityExpressionHandler createExpressionHandler() { 
    new DefaultMethodSecurityExpressionHandler(roleHierarchy: SecurityConfiguration.roleHierarchy()) 
    } 

    @Override 
    protected AccessDecisionManager accessDecisionManager() { 
    AffirmativeBased manager = super.accessDecisionManager() as AffirmativeBased 
    manager.decisionVoters.clear() 
    manager.decisionVoters << SecurityConfiguration.roleVoter() 
    manager 
    } 

} 

我是删除其他选民,只需在AccessDecisionManager中添加我的RoleHierarchyVoter,但如果需要,您可以保留其他选民。在我的情况下,我只使用@Secured注释,因此不需要其他人。这是在任何地方都没有提到的使用@Secured注释工作的部分。


另一种解决方案就是创建一个RoleHierarchy豆与层次配置,并将其注入到您的自定义验证过滤器,你会认证用户,并通过有关部门通过调用UsernamePasswordAuthenticationToken:

roleHierarchy.getReachableGrantedAuthorities(authorityFromUserDetails) 

这第二如果您不使用任何自定义授权,解决方案有点棘手,但在我的情况下,它更简单。