Spring Security 3.2 - 配置全局方法安全性以使用角色层次结构

Posted

技术标签:

【中文标题】Spring Security 3.2 - 配置全局方法安全性以使用角色层次结构【英文标题】:Spring Security 3.2 - configuring global method security to use role hierarchy 【发布时间】:2015-02-15 03:08:58 【问题描述】:

使用 Spring Security 3.2.5 和 Spring 4.1.2,100% Java 配置

我们的 web 应用启用了全局方法安全性,并使用 @PreAuthorize 注释了服务方法 - 一切都按预期工作。我正在尝试添加角色层次结构并且根本没有成功。这是我想要实现的层次结构:

ROLE_ADMIN 可以访问 ROLE_USER 可以访问的所有方法。 ROLE_USER 可以访问 ROLE_DEFAULT 可以访问的所有方法。

尽管我尽了最大努力,但具有 ROLE_ADMIN 的用户在执行导致调用带有 @PreAuthorized("hasAuthority('ROLE_DEFAULT')") 注释的方法的操作时收到 403

下面是相关配置代码:

AppInitializer

public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer

  @Override
  protected Class<?>[] getRootConfigClasses()
  
    return new Class[]
    
      AppConfig.class, SecurityConfig.class
    ;
  

  @Override
  protected Class<?>[] getServletConfigClasses()
  
    return new Class[]
    
      MvcConfig.class
    ;
  
  // other methods not shown for brevity

AppConfig.java

@Configuration
@ComponentScan(basePackages="myapp.config.profile", "myapp.dao", "myapp.service", "myapp.security")
public class AppConfig

  @Autowired
  public void configureGlobal(AuthenticationManagerBuilder auth,
                              AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> detailSvc) throws Exception
  
    PreAuthenticatedAuthenticationProvider authProvider = new PreAuthenticatedAuthenticationProvider();
    authProvider.setPreAuthenticatedUserDetailsService(detailSvc);
    auth.authenticationProvider(authProvider);
  
  // other methods not shown for brevity

SecurityConfig.java

@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter

  @Override
  protected void configure(HttpSecurity http) throws Exception
  
    PKIAuthenticationFilter pkiFilter = new PKIAuthenticationFilter();
    pkiFilter.setAuthenticationManager(authenticationManagerBean());

    http.authorizeRequests()
        .antMatchers("/app/**").fullyAuthenticated()
        .and()
        .anonymous().disable()
        .jee().disable()
        .formLogin().disable()
        .csrf().disable()
        .x509().disable()
        .addFilter(pkiFilter)
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
  

  @Override
  public void configure(WebSecurity web) throws Exception
  
    // ignore everything but /app/*
    web.ignoring().regexMatchers("^(?!/app/).*");
  

MvcConfig.java

@Configuration
@EnableWebMvc
@ComponentScan("myapp.controller")
public class MvcConfig extends WebMvcConfigurerAdapter

  // resource handlers, content negotiation, message converters configured here

在与SecurityConfig 相同的包中(因此它是AppConfig 组件扫描的一部分)我有这个类:

GlobalMethodSecurityConfig.java

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class GlobalMethodSecurityConfig extends GlobalMethodSecurityConfiguration

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

  @Bean
  public RoleVoter roleVoter()
  
    return new RoleHierarchyVoter(roleHierarchy);
  

  @Bean
  @Override
  protected AccessDecisionManager accessDecisionManager()
  
    return new AffirmativeBased(Arrays.asList(roleVoter()));
  

  // The method below was added in an attempt to get things working but it is never called
  @Override
  protected MethodSecurityExpressionHandler createExpressionHandler()
  
    DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler();
    handler.setRoleHierarchy(roleHierarchy());
    return handler;
  

在另一次尝试中,我进行了 AppConfig 扩展 GlobalMethodSecurityConfiguration,但具有 ROLE_ADMIN 的用户无法调用需要 ROLE_DEFAULT 访问权限的方法。

我确定我在某处错误地配置了某些东西,但尽管阅读了有关使用角色层次结构配置全局方法安全性的所有内容,但我无法弄清楚我哪里出错了。看来使用 XML 配置这将是微不足道的,但 Java 配置解决方案却让我望而却步。

【问题讨论】:

这不是对您问题的确切答案,但这是多年来对我有用的方法:***.com/a/22612076/280244 【参考方案1】:

我刚刚完成了所有这些设置并在这里回答了同样的问题:Spring Boot + Spring Security + Hierarchical Roles

希望这会有所帮助。

【讨论】:

【参考方案2】:

由于这个问题不断获得意见,我想我会发布一个跟进它。问题似乎出在这条线上

roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER > ROLE_DEFAULT");

我不记得我为什么要这样写层次结构,但它不正确。 API for that method 这样处理同样的情况:

角色层次结构: ROLE_A > ROLE_B 和 ROLE_B > ROLE_C。直接分配的权限: ROLE_A。可访问的权限: ROLE_A、ROLE_B、ROLE_C。

最终很明显,分层模型不适合我们的角色,因此我们实施了一组更细粒度的权限映射到角色,如 Spring Security Reference 中所述:

对于更复杂的要求,您可能希望在应用程序所需的特定访问权限和分配给用户的角色之间定义逻辑映射,在加载用户信息时在两者之间进行转换。

【讨论】:

以上是关于Spring Security 3.2 - 配置全局方法安全性以使用角色层次结构的主要内容,如果未能解决你的问题,请参考以下文章

每个用户一个会话 spring security 3.2

将 AccessDeniedException 传播到 Spring Security 3.2

Spring Security 3.2 CSRF 禁用特定 URL

Spring 3.2:基于 Spring Security 角色过滤 Jackson JSON 输出

Spring Security 3.2:不考虑@Secured注解

Spring Security 3.2 令牌认证