Java 使用Spring Boot的角色层次结构和OAuth2安全性

Java 使用Spring Boot的角色层次结构和OAuth2安全性,java,spring-boot,oauth-2.0,spring-security-oauth2,Java,Spring Boot,Oauth 2.0,Spring Security Oauth2,我知道有很多关于角色层次结构的线程,但是我找不到任何与OAuth2结合的示例 所以, 大多数线程都指出我需要实现rolehierarchbean: Beans.java @EnableJpaRepositories(basePackages = "com.template.service.repository") @EnableAspectJAutoProxy @ComponentScan @Configuration public class Beans { @Bean public Item

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

所以, 大多数线程都指出我需要实现
rolehierarch
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();
}
}
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");
    }
}
}
@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();
} 
}
接下来,我需要
@Autowire
将这个bean连接到我的
WebSecurityConfigurerAdapter
。但是,因为我使用的是OAuth2安全性,所以我在
ResourceServerConfigurerAdapter
中配置了
HttpSecurity

OAuth2.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();
}
}
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");
    }
}
}
@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 user凭据的请求以以下结尾:

{
  "error": "access_denied",
  "error_description": "Access is denied"
}
当我将
hasRole(“开发者”)
切换到
hasRole(“至高无上”)
时,一切正常

我使用的是Spring Boot 1.5.2和Spring Security OAuth 2.1.0.RELEASE

更新


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

您如何看待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);
    }

它可以更好地结构化和封装,但你知道我的意思,不是吗?。。。我认为它很好用。我希望这能帮助你…

这就是它成功的原因。我已经测试过了

角色高级>角色开发者>角色管理员

将博客编码如下

@Bean
public static RoleHierarchyImpl roleHierarchy() {

    RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
    roleHierarchy.setHierarchy("ROLE_SUPREME > ROLE_DEVELOPER > ROLE_ADMIN ");
    return roleHierarchy;

}
我希望这对你有帮助