使用 Spring Boot 的角色层次结构和 OAuth2 安全性
Posted
技术标签:
【中文标题】使用 Spring Boot 的角色层次结构和 OAuth2 安全性【英文标题】:Role hierarchy and OAuth2 Security using Spring Boot 【发布时间】: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 资源服务器是怎么回事呢?
【问题讨论】:
【参考方案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;
希望对你有所帮助。
【讨论】:
以上是关于使用 Spring Boot 的角色层次结构和 OAuth2 安全性的主要内容,如果未能解决你的问题,请参考以下文章
Spring Security 3.2 - 配置全局方法安全性以使用角色层次结构
Spring security @secure 不适用于角色层次结构
Spring Webflux Security 中的角色层次结构
Spring Security 3.1.4 taglib 授权/身份验证不适用于 Tomcat 7 上 JSF 2.2 中的角色层次结构