我们有一个授权数据库,其中包含应用程序ID、角色和Map到每个应用程序的角色的用户。在advice on thread之后,我如何基于resourceId将用户角色Map到oauth2范围/权限?
忽略我上面提到的权限数据库,我是否在下面的代码中根据用户和资源ID将角色“USER”、“READER”、“WRITER”Map到oauth2范围/权限?
用户验证/授权配置
@Configuration
@Order(-10)
protected static class LoginConfig extends WebSecurityConfigurerAdapter {
....
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// auth.parentAuthenticationManager(authenticationManager);
// @formatter:off
auth.inMemoryAuthentication()
.withUser("admin").password("admin")
.roles("ADMIN", "USER", "READER", "WRITER")
.and()
.withUser("user").password("password")
.roles("USER")
.and()
.withUser("audit").password("audit")
.roles("USER", "ADMIN", "READER");
// @formatter:on
}
}
OAuth2配置
@Configuration
@EnableAuthorizationServer
protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// @formatter:off
clients.inMemory()
.withClient("acme").secret("acmesecret")
.authorizedGrantTypes("authorization_code", "refresh_token", "password")
.scopes("openid")
.and()
.withClient("trusted").secret("shuush")
.authorizedGrantTypes("client_credentials")
.scopes("openid");
// @formatter:on
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.checkTokenAccess("isAuthenticated()");
}
}
更新1:
在配置中引入了一个自定义OAuth2RequestFactory以将checkUserScopes设置为true。虽然此设置适用于“client_credentails”,但对于“code”赠款则失败。对于“code”授权,DefaultOAuth2RequestFactory尝试Map客户端的权限(acme)而不是用户。另一个想法是实现ClientDetailsService,它添加客户端的权限(acme)基于登录用户(admin/user),但不确定如何从SecurityContext中获取登录用户,因为在授权步骤中它被客户端(acme)覆盖。
public class ScopeMappingOAuth2RequestFactory extends DefaultOAuth2RequestFactory {
private SecurityContextAccessor securityContextAccessor = new DefaultSecurityContextAccessor();
public ScopeMappingOAuth2RequestFactory(ClientDetailsService clientDetailsService) {
super(clientDetailsService);
super.setCheckUserScopes(true);
}
/**
* @param securityContextAccessor the security context accessor to set
*/
@Override
public void setSecurityContextAccessor(SecurityContextAccessor securityContextAccessor) {
this.securityContextAccessor = securityContextAccessor;
super.setSecurityContextAccessor(securityContextAccessor);
}
@Override
public AuthorizationRequest createAuthorizationRequest(Map<String, String> authorizationParameters) {
AuthorizationRequest request = super.createAuthorizationRequest(authorizationParameters);
if (securityContextAccessor.isUser()) {
request.setAuthorities(securityContextAccessor.getAuthorities());
}
return request;
}
}
并更新了相关代码以
@EnableAuthorizationServer
protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
private InMemoryClientDetailsService clientDetailsService;
private Map<String, ClientDetails> clientDetailsStore;
public InMemoryClientDetailsService clientDetailsService() {
if (clientDetailsService == null) {
clientDetailsStore = new HashMap<String, ClientDetails>();
InMemoryClientDetailsService m = new InMemoryClientDetailsService() {
@Override
public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException {
ClientDetails details = clientDetailsStore.get(clientId);
if (details == null) {
throw new NoSuchClientException("No client with requested id: " + clientId);
}
return details;
}
};
clientDetailsService = m;
}
return clientDetailsService;
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
InMemoryClientDetailsServiceBuilder builder = new InMemoryClientDetailsServiceBuilder() {
@Override
protected void addClient(String clientId, ClientDetails value) {
clientDetailsStore.put(clientId, value);
}
@Override
protected ClientDetailsService performBuild() {
return clientDetailsService();
}
};
clients.setBuilder(builder);
// @formatter:off
builder
.withClient("acme").secret("acmesecret")
.authorizedGrantTypes("authorization_code", "refresh_token", "password")
.scopes("openid", "apim.read", "apim.write")
.and()
.withClient("trusted").secret("shuush")
.authorizedGrantTypes("client_credentials")
.scopes("openid", "apim.read", "apim.write")
.authorities("openid", "apim.read", "apim.write");
// @formatter:on
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
endpoints.requestFactory(new ScopeMappingOAuth2RequestFactory(clientDetailsService()));
}
...
}
登录配置
Configuration
@Order(-10)
protected static class LoginConfig extends WebSecurityConfigurerAdapter {
....
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// auth.parentAuthenticationManager(authenticationManager);
// @formatter:off
auth.inMemoryAuthentication()
.withUser("admin").password("admin")
.roles("APIM.READ", "APIM.WRITE")
.and()
.withUser("user").password("password")
.roles("APIM.READ")
.and()
.withUser("audit").password("audit")
.roles("APIM.READ");
// @formatter:on
}
}
1条答案
按热度按时间uinbv5nw1#
我遇到了同样的问题,我还注意到代码运行了两次
checkUserScopes
方法。我发现缺少的是用户和客户端都需要有您想要返回的权限。因此,以这样的方式定义你的客户(根据自己的角色调整角色):
现在,客户端具有所需的权限user和admin。
并配置您的请求工厂: