2014-10-30 127 views
9

我試圖在我的Spring Boot應用程序中設置分層角色,但沒有成功。我已經完成了互聯網上不同地方所說的一切。但是我沒有一個能夠解決這個問題。Spring Boot + Spring Security +分層角色

這是我的SecurityConfig類的代碼。當我在ROLE_ADMIN用戶的應用程序中登錄時,它應該能夠從'/ users'中檢索數據,但目前我收到拒絕訪問異常。如果用戶具有ROLE_USER憑證,則它工作正常。 任何人都可以幫我弄清楚什麼是失敗? 在此先感謝。

@Configuration 
@EnableWebMvcSecurity 
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true) 
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 

    @Autowired 
    private SigpaUserDetailsService userDetailsService; 

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

    @Bean 
    public RoleHierarchyVoter roleVoter() {  
     return new RoleHierarchyVoter(roleHierarchy()); 
    } 

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

    @Bean 
    @SuppressWarnings(value = { "rawtypes" }) 
    public AffirmativeBased accessDecisionManager() {  
     List<AccessDecisionVoter> decisionVoters = new ArrayList<AccessDecisionVoter>(); 
     WebExpressionVoter webExpressionVoter = new WebExpressionVoter(); 
     webExpressionVoter.setExpressionHandler(expressionHandler()); 
     decisionVoters.add(webExpressionVoter); 
     decisionVoters.add(roleVoter()); 
     return new AffirmativeBased(decisionVoters); 
    } 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http 
      .authorizeRequests() 
      .accessDecisionManager(accessDecisionManager()) 
      .expressionHandler(expressionHandler()) 
      .antMatchers("https://stackoverflow.com/users/**") 
       .access("hasRole('ROLE_USER')") 
      .anyRequest().authenticated(); 
     http 
      .formLogin() 
       .loginPage("/login").permitAll() 
       .and() 
      .logout() 
       .permitAll(); 
    } 

    @Override 
    protected void configure(AuthenticationManagerBuilder registry) 
      throws Exception { 
     registry.userDetailsService(userDetailsService); 
    } 
} 

更新:這裏是你的建議更新的代碼,但仍無法工作的。

回答

3

您需要在web表情投票器上設置角色層次結構。喜歡的東西:

DefaultWebSecurityExpressionHandler expressionHandler = new DefaultWebSecurityExpressionHandler(); 
expressionHandler.setRoleHierarchy(roleHierarchy); 
webExpressionVoter.setExpressionHandler(expressionHandler); 

更新:您也可以嘗試設置上述表達式處理程序是這樣的:

http 
    .authorizeRequests() 
    .expressionHandler(expressionHandler) 
    ... 
+0

它不這樣工作。我仍然收到相同的訪問拒絕異常 – Mario 2014-10-30 21:53:04

+0

@Mario嘗試我的更新。 – holmis83 2014-10-31 08:05:37

+0

我昨天已經這麼做了......我不知道爲什麼不工作,因爲我已經盡一切努力沒有取得任何成功。 – Mario 2014-10-31 12:04:57

3

必須設置在MethodSecurityExpressionHandler的角色層次:

@Configuration 
@EnableGlobalMethodSecurity(prePostEnabled = true) 
public static class GlobalMethodSecurityConfig extends GlobalMethodSecurityConfiguration { 
    @Autowired 
    private RoleHierarchy roleHierarchy; 

    @Override 
    protected MethodSecurityExpressionHandler createExpressionHandler() { 
     final DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler(); 
     handler.setRoleHierarchy(this.roleHierarchy); 
     return handler; 
    } 
} 

查詢Javadoc for @EnableGlobalMethodSecurity瞭解更多信息。尤其要注意:EnableGlobalMethodSecurity仍然必須包含在擴展GlobalMethodSecurityConfiguration的類中以確定設置。

7

我剛剛通過這些設置,所以一定會讓你現在運行。這是交易:

你帶來了這個註釋@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)但沒有顯示任何代碼使用前/後授權/過濾器,所以我不知道你是否真的需要它。

  1. 如果您不需要這個類/方法級安全性/過濾那麼所有你需要做的是:

    @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; 
     } 

http 
     .authorizeRequests() 
     .expressionHandler(webExpressionHandler()) 

你不」如果您只需要引入角色層次結構,則必須使用您自己的accessDecisionManager進行覆蓋。

  1. 如果您還需要類/方法級別的安全性,即在你的方法/類使用PreAuthorize, PostAuthorize, PreFilter, PostFilter也會顯示在您的類路徑創建這樣一個@Configuration(並從GlobalMethodSecurityConfig類中刪除@EnableGlobalMethodSecurity註釋):

    @Configuration 
    @EnableGlobalMethodSecurity(prePostEnabled=true) 
    public class AnyNameYouLike extends GlobalMethodSecurityConfiguration { 
    
    @Resource 
    private RoleHierarchy roleHierarchy; 
    
    @Override 
    protected MethodSecurityExpressionHandler createExpressionHandler() { 
        DefaultMethodSecurityExpressionHandler expressionHandler = (DefaultMethodSecurityExpressionHandler) super.createExpressionHandler(); 
        expressionHandler.setRoleHierarchy(roleHierarchy); 
        return expressionHandler; 
    } 
    

    }

我會給將GlobalMethodSecurityConfig命名爲此新類,並將當前的GlobalMethodSecurityConfig類更改爲WebSecurityConfig或其他內容以反映它是Web層的安全設置。

我在webSecurityConfig中定義了RoleHierarchy bean,並在globalMethodSecurityConfig中注入/使用它,但只要您不需要創建2個bean,您可以按照自己喜歡的方式進行操作。

希望這會有所幫助。

+0

嗨,謝謝你的回答!不幸的是,Spring不允許我從我的'WebSecurityConfig'類中刪除'@ EnableGlobalMethodSecurity'註解 - 我得到'IllegalArgumentException:需要ServletContext來配置默認的servlet處理'。任何幫助讚賞 – kiedysktos 2017-04-14 07:39:11

+0

好的,我找到了一個解決方案。看起來你在第2點的建議並不是那麼好,因爲對我而言,它反其道而行之。在這裏看到一個答案:http://stackoverflow.com/questions/43468285/springboot-method-based-hierarchical-roles-security-servletcontext-is-require/43473615#43473615 – kiedysktos 2017-04-18 13:30:15

0

啓用方法級別安全性(即@EnableGlobalMethodSecurity(prePostEnabled = true))以及支持WebSecurityConfigurerAdapter上的Hierarchical-role。

1.只需要在@Bean註釋的任何其他類上分離RoleHierarchy
2.在WebSecurityConfigurerAdapter上使用@Autowired注入它。 它在我的項目上完美地工作。

請看看我的代碼。

WeSecurityConfig.class

@Configuration 
    @EnableGlobalMethodSecurity(prePostEnabled = true) 
    @EnableWebSecurity 
    public class AppSecurityConfig extends WebSecurityConfigurerAdapter{ 
    @Autowired 
    private RoleHierarchy roleHierarchy; 

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


@Override 
public void configure(WebSecurity web) throws Exception{ 
    super.configure(web); 
    web.ignoring().antMatchers("/static/**"); 
} 

@Override 
public void configure(HttpSecurity http) throws Exception{ 
    http. 
      authorizeRequests() 
      .expressionHandler(webExpressionHandler()) 
      .antMatchers("/static/**","/bower_components/**","/").permitAll() 
      .antMatchers("/user/login","/user/login?error").anonymous() 
      .anyRequest().authenticated() 
      .and() 
      .formLogin().loginPage("/user/login").passwordParameter("password").usernameParameter("username") 
      .defaultSuccessUrl("/") 
      .permitAll() 
      .and() 
      .logout().logoutUrl("/user/logout") 
      .logoutSuccessUrl("/user/login?logout") 
      .and().csrf(); 

} 


@Override 
public void configure(AuthenticationManagerBuilder auth) throws Exception{ 
    auth.authenticationProvider(daoAuthenticationProvider()); 
} 

public DaoAuthenticationProvider daoAuthenticationProvider(){ 
    final DaoAuthenticationProvider auth = new DaoAuthenticationProvider(); 
    auth.setUserDetailsService(userDetailService); 
    auth.setPasswordEncoder(passwordEncoder); 
    return auth; 
} 

}

BeanConfiguration.class

@Configuration 
public class BeanConfiguration { 

@Bean 
public RoleHierarchy roleHierarchy(){ 
    RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl(); 
    /* tricks lies here */ 
    roleHierarchy.setHierarchy("ROLE_SUPREME > ROLE_ADMIN ROLE_ADMIN > ROLE_OPERATOR ROLE_OPERATOR > ROLE_GUEST"); 
    return roleHierarchy; 
} 

}

希望它可以幫助你。

相關問題