Spring Security Role Hierarchy无法使用Java Config工作


问题内容

首先,我是Java Spring
Framework的新手。如果我没有提供足够的信息,请原谅我。我试图将RoleHierarchy添加到我的应用程序中,但是没有用。以下是我尝试过的代码。


SecurityConfig.java

// These config is try to set up a user Role Hierarchy
@Bean
public RoleHierarchy roleHierarchy() {
  System.out.println("arrive public RoleHierarchy roleHierarchy()");
  RoleHierarchyImpl r = new RoleHierarchyImpl();
  r.setHierarchy("ROLE_ADMIN > ROLE_STAFF");
  r.setHierarchy("ROLE_STAFF > ROLE_USER");
  r.setHierarchy("ROLE_DEVELOPER > ROLE_USER");
  r.setHierarchy("ROLE_USER > ROLE_GUEST"); 
  return r;
}

@Bean
public AffirmativeBased defaultAccessDecisionManager(RoleHierarchy roleHierarchy){
  System.out.println("arrive public AffirmativeBased defaultAccessDecisionManager()");
  List<AccessDecisionVoter> decisionVoters = new ArrayList<>();

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

  decisionVoters.add(webExpressionVoter);
  decisionVoters.add(roleHierarchyVoter(roleHierarchy));
  // return new AffirmativeBased(Arrays.asList((AccessDecisionVoter) webExpressionVoter));
  return new AffirmativeBased(decisionVoters);
}

@Bean
public RoleHierarchyVoter roleHierarchyVoter(RoleHierarchy roleHierarchy) {
  System.out.println("arrive public RoleHierarchyVoter roleHierarchyVoter");
  return new RoleHierarchyVoter(roleHierarchy);
}

@Override
protected void configure(HttpSecurity http) throws Exception {
  // skipping some codes
  http
    // skipping some codes
    .accessDecisionManager(defaultAccessDecisionManager(roleHierarchy()))
  // skipping some codes
}

MethodSecurityConfig.java

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {

  @Inject
  private SecurityConfig securityConfig;

  @Override
  protected AuthenticationManager authenticationManager() throws Exception {
    return securityConfig.authenticationManagerBean();
  }

  @Override
  protected MethodSecurityExpressionHandler createExpressionHandler() {
    System.out.println("arrive protected MethodSecurityExpressionHandler createExpressionHandler()");
    DefaultMethodSecurityExpressionHandler d = new DefaultMethodSecurityExpressionHandler();
    d.setRoleHierarchy(securityConfig.roleHierarchy());
    return d;
  }

}

我有UserDetailsServiceImpl implements UserDetailsService提供的principalAuthentication并且GrantedAuthority

最后,我有一些API:

@PreAuthorize("hasRole('ROLE_STAFF')")
@RequestMapping(value = "/api/v1/contactUs", method = RequestMethod.GET)

@PreAuthorize("hasRole('ROLE_DEVELOPER')")
@RequestMapping(value = "/api/v1/system", method = RequestMethod.GET)

现在的问题是,如果我以ROLE_STAFF,ROLE_DEVELOPER,ROLE_ADMIN登录,则会得到以下结果。

| API       | ROLE_STAFF | ROLE_DEVELOPER | ROLE_ADMIN |
|-----------|------------|----------------|------------|
| contactUs | 200        | 403            | 403        |
| system    | 403        | 200            | 403        |

如您所见ROLE_STAFFROLE_DEVELOPER工作正常。但是我想ROLE_ADMIN同时扮演这两个角色,但这没有用。

仅供参考,我正在使用spring-security 3.2.5.RELEASE


问题答案:

问题出在RoleHierachy中,应该像这样:

@Bean
public RoleHierarchy roleHierarchy() {
  RoleHierarchyImpl r = new RoleHierarchyImpl();
  r.setHierarchy("ROLE_ADMIN > ROLE_STAFF and ROLE_ADMIN > ROLE_DEVELOPER and ROLE_STAFF > ROLE_USER and ROLE_DEVELOPER > ROLE_USER");
  return r;
}

继续通话setHierarchy()会覆盖之前的设置