2014-10-30 128 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; 
} 

}

希望它可以帮助你。

相关问题