一、resource_id 的作用
Spring Security OAuth2 架构上分为 Authorization Server 认证服务器和 Resource Server 资源服务器。咱们能够为每一个 Resource Server(一个微服务实例)设置一个 resourceid。Authorization Server 给 client 第三方客户端受权的时候,能够设置这个 client 能够拜访哪一些 Resource Server 资源服务,如果没设置,就是对所有的 Resource Server 都有拜访权限。
二、ResourceServer 如何设置 ResourceID
在每个 ResourceServer 实例上设置 resourceId,该 resourceId 作为该服务资源的惟一标识。(如果同一个微服务资源部署多份,resourceId 雷同)
@Configuration
@EnableResourceServer
public class OAuth2ResourceServer extends ResourceServerConfigurerAdapter {
private static final String DEMO_RESOURCE_ID = "test-resource";
@Override
public void configure(ResourceServerSecurityConfigurer resources) {resources.resourceId(DEMO_RESOURCE_ID)
//...... 还能够有有其余的配置
}
}
三、AuthorizationServer 如何设置 ResourceIDs
在 AuthorizationServer 为客户端 client 配置 ResourceID 的目标是:限度某个 client 能够拜访的资源服务。
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// 配置客户端存储到 db 代替原来得内存模式
JdbcClientDetailsService clientDetailsService = new JdbcClientDetailsService(dataSource);
clientDetailsService.setPasswordEncoder(passwordEncoder);
clients.withClientDetails(clientDetailsService);
}
这里须要应用 JdbcClientDetailsService 类和数据库表 oauth_client_details 进行配置的长久化存储,以及动静配置。
三、ResourceID 在哪验证
ResourceID 当然是在 Resource Server 资源服务器进行验证(你能不能拜访我的资源,当然由我本人来验证)。当资源申请发送到 Resource Server 的时候会携带 access_token,Resource Server 会依据 access_token 找到 client_id,进而找到该 client 能够拜访的 resource_ids。如果 resource_ids 蕴含 ResourceServer 本人设置 ResourceID,这关就过来了,就能够持续进行其余的权限验证。
- @EnableResourceServer 会给 Spring Security 的 FilterChan 增加一个 OAuth2AuthenticationProcessingFilter 过滤器,过滤所有的资源申请。
- OAuth2AuthenticationProcessingFilter 会应用 OAuth2AuthenticationManager 来验证 token。验证 Token 的时候会去 oauth_client_details 表加载 client 配置信息。
如果 AuthorizationServer 认证 client1 能够拜访 test-resource,但 client1 去拜访了 oauth-rs,会响应如下信息:
{"error":"access_denied","error_description":"Invalid token does not contain resource id (oauth-rs)"}
具体实现 resource_id 验证的源码:OAuth2AuthenticationManager#authenticate(Authentication authentication)
public Authentication authenticate(Authentication authentication) throws AuthenticationException {if (authentication == null) {throw new InvalidTokenException("Invalid token (token not found)");
}
String token = (String) authentication.getPrincipal();
OAuth2Authentication auth = tokenServices.loadAuthentication(token);
if (auth == null) {throw new InvalidTokenException("Invalid token:" + token);
}
Collection<String> resourceIds = auth.getOAuth2Request().getResourceIds();
if (resourceId != null && resourceIds != null && !resourceIds.isEmpty() && !resourceIds.contains(resourceId)) {throw new OAuth2AccessDeniedException("Invalid token does not contain resource id (" + resourceId + ")");
}
checkClientDetails(auth);
if (authentication.getDetails() instanceof OAuth2AuthenticationDetails) {OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authentication.getDetails();
// Guard against a cached copy of the same details
if (!details.equals(auth.getDetails())) {
// Preserve the authentication details from the one loaded by token services
details.setDecodedDetails(auth.getDetails());
}
}
auth.setDetails(authentication.getDetails());
auth.setAuthenticated(true);
return auth;
}
上面这段便是验证 resourceid 的中央
Collection<String> resourceIds = auth.getOAuth2Request().getResourceIds();
if (resourceId != null && resourceIds != null && !resourceIds.isEmpty() && !resourceIds.contains(resourceId)) {throw new OAuth2AccessDeniedException("Invalid token does not contain resource id (" + resourceId + ")");
}
在 Spring Security 的 FilterChain 中,OAuth2AuthenticationProcessingFilter 在 FilterSecurityInterceptor 的后面,所以会先验证 client 有没有此 resource 的权限,只有在有此 resource 的权限的状况下,才会再去做进一步的进行其余验证的判断。
欢送关注我的博客,外面有很多精品合集
- 本文转载注明出处(必须带连贯,不能只转文字):字母哥博客。
感觉对您有帮忙的话,帮我点赞、分享!您的反对是我不竭的创作能源!。另外,笔者最近一段时间输入了如下的精品内容,期待您的关注。
- 《手摸手教你学 Spring Boot2.0》
- 《Spring Security-JWT-OAuth2 一本通》
- 《实战前后端拆散 RBAC 权限管理系统》
- 《实战 SpringCloud 微服务从青铜到王者》
- 《VUE 深入浅出系列》