首先,根据Spring文档,如果我想将用户角色映射到作用域,我应该使用setCheckUserScopes(true)来设置DefaultOAuth2RequestFactory。因此,一种方法是注入自己的DefaultOAuth2RequestFactory bean,正如文档所述:
The AuthorizationServerEndpointsConfigurer allows you to inject a custom OAuth2RequestFactory so you can use that feature to set up a factory if you use @EnableAuthorizationServer.
然后我执行
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends
AuthorizationServerConfigurerAdapter {
...
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints.authenticationManager(authenticationManager)
.tokenStore(tokenStore)
.tokenServices(tokenServices());
endpoints
.getOAuth2RequestFactory(); // this doesn't return me my own DefaultOAuth2RequestFactory
}
@Bean
@Primary
public OAuth2RequestFactory defaultOAuth2RequestFactory() {
DefaultOAuth2RequestFactory defaultOAuth2RequestFactory = new DefaultOAuth2RequestFactory(
clientDetailsService);
defaultOAuth2RequestFactory.setCheckUserScopes(true);
return defaultOAuth2RequestFactory;
}
}
编辑
我忽略了AuthorizationServerEndpointsConfigurer中的requestFactory()方法。这是将它传递给Spring Security的正确方式。将OAuth2RequestFactory bean设置为主要的并没有起作用。我删除了一些内容,以便关注真正的问题:
在这个观察之后,实际的问题是:
据我所知,如果用户拥有A和B权限,而应用程序只有A范围,则他只会得到'A'范围。但事实并非如此。实际上发生的是,如果应用程序具有A范围,并且应用程序(而不是用户)拥有A和B权限,则用户获得A。但这毫无意义。
这是DefaultOAuth2RequestFactory方法解析用户范围的过程:
private Set<String> extractScopes(Map<String, String> requestParameters, String clientId) {
... // I avoid some unimportant lines to not make this post so long
if ((scopes == null || scopes.isEmpty())) {
scopes = clientDetails.getScope();
}
if (checkUserScopes) {
scopes = checkUserScopes(scopes, clientDetails);
}
return scopes;
}
private Set<String> checkUserScopes(Set<String> scopes, ClientDetails clientDetails) {
if (!securityContextAccessor.isUser()) {
return scopes;
}
Set<String> result = new LinkedHashSet<String>();
Set<String> authorities = AuthorityUtils.authorityListToSet(securityContextAccessor.getAuthorities());
for (String scope : scopes) {
if (authorities.contains(scope) || authorities.contains(scope.toUpperCase())
|| authorities.contains("ROLE_" + scope.toUpperCase())) {
result.add(scope);
}
}
return result;
}
这是一个 bug 吗?如果我错了,请告诉我。谢谢。