将用户角色映射到 oauth2 范围/权限

问题描述 投票:0回答:1

我们有一个权利数据库,其中包含应用程序 ID、角色以及映射到每个应用程序角色的用户。遵循关于线程的建议如何根据resourceId将用户角色映射到oauth2范围/权限?

忽略我上面提到的权利数据库,我是否可以根据下面代码中的用户和资源 ID 将角色“USER”、“READER”、“WRITER”映射到 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”授权则失败。对于“代码”授权,DefaultOAuth2RequestFactory 尝试在授权步骤中为客户端(acme)而非用户映射权限。 另一种想法是实现ClientDetailsService,根据登录用户(管理员/用户)添加客户端(acme)的权限,但不确定如何从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 } }
    
spring-security spring-security-oauth2
1个回答
0
投票
我遇到了同样的问题,我还注意到代码运行了

checkUserScopes

 方法两次。我发现缺少的是用户和客户端都需要拥有您想要返回的权限。

因此,以这样的方式定义您的客户(根据您自己的角色调整角色):

@Bean public ClientDetailsService clientDetailsService() { Map<String, ClientDetails> clientDetailsStore = new HashMap<>(); Collection<String> scope = new HashSet<>(); scope.add("user"); scope.add("admin"); Collection<GrantedAuthority> authorities = new HashSet<>(); authorities.add(new SimpleGrantedAuthority("ROLE_USER")); authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN")); Collection<String> authorizedGrantTypes = new HashSet<>(); authorizedGrantTypes.add("authorization_code"); BaseClientDetails clientDetails = new BaseClientDetails(); clientDetails.setClientId("clientid"); clientDetails.setClientSecret("{noop}secret"); //noop for Spring Security 5 clientDetails.setScope(scope); clientDetails.setAuthorities(authorities); clientDetails.setAuthorizedGrantTypes(authorizedGrantTypes); clientDetailsStore.put("clientid", clientDetails); InMemoryClientDetailsService clientDetailsService = new InMemoryClientDetailsService(); clientDetailsService.setClientDetailsStore(clientDetailsStore); return clientDetailsService; }

现在客户端拥有所需的权限 user 和 admin。

并配置您的请求工厂:

@Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) { DefaultOAuth2RequestFactory defaultOAuth2RequestFactory = new DefaultOAuth2RequestFactory(clientDetailsService()); defaultOAuth2RequestFactory.setCheckUserScopes(true); endpoints.requestFactory(defaultOAuth2RequestFactory); }
    
© www.soinside.com 2019 - 2024. All rights reserved.