【问题标题】:Role hierarchy and OAuth2 Security using Spring Boot使用 Spring Boot 的角色层次结构和 OAuth2 安全性
【发布时间】:2017-08-07 23:47:58
【问题描述】:

我知道有很多关于角色层次结构的线程,但是我找不到任何与 OAuth2 结合的示例。

所以, 大多数线程都指向我需要实现RoleHierarchy bean:

Beans.java

@EnableJpaRepositories(basePackages = "com.template.service.repository")
@EnableAspectJAutoProxy
@ComponentScan
@Configuration
public class Beans {
@Bean
public ItemService itemsService(ItemsRepository itemsRepository) {
    return new ItemService(itemsRepository);
}

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

@Bean
public DtoMapper dtoMapper() {
    return new DtoMapper();
}
}

接下来,我需要 @Autowire 这个 bean 到我的 WebSecurityConfigurerAdapter。但是因为我使用的是 OAuth2 安全性,所以我在 ResourceServerConfigurerAdapter 内部配置了 HttpSecurity

OAuth2.java

public class OAuth2 {
@EnableAuthorizationServer
@Configuration
@ComponentScan
public static class AuthorizationServer extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManagerBean;
    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("trusted_client")
                .authorizedGrantTypes("password", "refresh_token")
                .scopes("read", "write");
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManagerBean).userDetailsService(userDetailsService);
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.allowFormAuthenticationForClients();
    }
}

@EnableResourceServer
@Configuration
@ComponentScan
public static class ResourceServer extends ResourceServerConfigurerAdapter {

    @Autowired
    private RoleHierarchy roleHierarchy;

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

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests().expressionHandler(webExpressionHandler())
                .antMatchers("/api/**").hasRole("DEVELOPER");
    }
}
}

Security.java

@EnableWebSecurity
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
@Configuration
@ComponentScan
public class Security extends WebSecurityConfigurerAdapter {

@Autowired
private UserDetailsService userDetailsService;

@Bean
public JpaAccountDetailsService userDetailsService(AccountsRepository accountsRepository) {
    return new JpaAccountDetailsService(accountsRepository);
}

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

@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
}

@Bean
public PasswordEncoder passwordEncoder(){
    return new BCryptPasswordEncoder();
} 
}

但是层次结构不起作用。带有 SUPREME 用户凭据的请求以:

{
  "error": "access_denied",
  "error_description": "Access is denied"
}

当我将 hasRole("DEVELOPER") 切换到 hasRole("SUPREME") 时 - 一切正常。

我正在使用 Spring Boot 1.5.2 和 Spring Security OAuth 2.1.0.RELEASE

更新

当我评论所有 OAuth2.java 类并将 webExpressionHandler() 方法签名移动到 Security.java 类时 - 角色层次结构工作正常。那么 OAuth2 资源服务器是怎么回事呢?

【问题讨论】:

    标签: java spring-boot oauth-2.0 spring-security-oauth2


    【解决方案1】:

    您如何看待 ResourceServer 中的这种方法?

       @Bean
        public RoleHierarchyImpl roleHierarchy() {
            RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
            roleHierarchy.setHierarchy("ROLE_SUPREME > ROLE_DEVELOPER ROLE_DEVELOPER > ROLE_ADMIN  ROLE_ADMIN > ROLE_USER")         return roleHierarchy;
        }
    
    
        @Bean
        public RoleHierarchyVoter roleVoter() {
            return new RoleHierarchyVoter(roleHierarchy());
        }
    
    
        @Bean
        public AffirmativeBased defaultOauthDecisionManager(RoleHierarchy roleHierarchy){ //
    
          List<AccessDecisionVoter> decisionVoters = new ArrayList<AccessDecisionVoter>();
    
          // webExpressionVoter
          OAuth2WebSecurityExpressionHandler expressionHandler = new OAuth2WebSecurityExpressionHandler();
          expressionHandler.setRoleHierarchy(roleHierarchy);
          WebExpressionVoter webExpressionVoter = new WebExpressionVoter();
          webExpressionVoter.setExpressionHandler(expressionHandler);
          decisionVoters.add(webExpressionVoter);
          decisionVoters.add(roleVoter());
          return new AffirmativeBased(decisionVoters);
        }
    

    还有

    http
                    .authorizeRequests()
                    .accessDecisionManager(defaultOauthDecisionManager(roleHierarchy()))
                    //etc...
    

    它可以更好地结构化和封装,但你知道我的意思,不是吗?...我认为它工作得很好。我希望这会对你有所帮助...

    【讨论】:

      【解决方案2】:

      这样就成功了。我已经测试过了。

      ROLE_SUPREME > ROLE_DEVELOPER > ROLE_ADMIN

      代码博客如下

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

      希望对你有所帮助。

      【讨论】:

        猜你喜欢
        • 2015-02-15
        • 2015-05-22
        • 1970-01-01
        • 1970-01-01
        • 2012-07-11
        • 2019-11-25
        • 2019-12-28
        • 2016-01-03
        • 2012-12-01
        相关资源
        最近更新 更多