2015-10-06 209 views
0

我遇到了一些問題,試圖在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://stackoverflow.com/questions/29888458/spring-security-role-hierarchy-not-working-using-java-config,但有什麼辦法可以擺脫antMatchers,因爲我只是想使用@Secured註釋 – Lukehey

回答

1

我也希望有一個使用@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) 

這第二如果您不使用任何自定義授權,解決方案有點棘手,但在我的情況下,它更簡單。