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

时间:2014-12-16 17:51:41

标签: java spring security spring-mvc spring-security

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

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

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

尽管我付出了最大的努力,但是当做一些导致调用注释为@PreAuthorized("hasAuthority('ROLE_DEFAULT')")

的方法时,使用ROLE_ADMIN的用户会收到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配置解决方案让我望而却步。

2 个答案:

答案 0 :(得分:0)

我刚刚通过所有这些设置并在此回答同样的问题:Spring Boot + Spring Security + Hierarchical Roles

希望这有帮助。

答案 1 :(得分:0)

由于这个问题不断得到观点,我认为我会发布一个后续行动。问题似乎与行

有关

complexStartUpRoutine

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

  

角色层次结构:ROLE_A&gt; ROLE_B和ROLE_B&gt; ROLE_C。
  直接分配权限: ROLE_A。
  可访问权限: ROLE_A,ROLE_B,ROLE_C。

最后很明显,分层模型并不适合我们的角色,所以我们改为实现映射到角色的更细粒度的权限集,如Spring Security Reference中所述:

  

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