这是我参与2022首次更文挑战的第8天,活动详情查看:2022首次更文挑战
上一篇(《Spring Security OAuth 之 @EnableAuthorizationServer 干了啥? 》)试着分析了 @EnableAuthorizationServer 注解是如何完成授权服务器的配置的,这篇来分析 @EnableResourceServer 是如何完成资源服务器配置的。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(ResourceServerConfiguration.class)
public @interface EnableResourceServer {
}
在 EnableResourceServer 中,通过 @``Import 注解,导入了 ResourceServerConfiguration 配置类。我们找到它的源码,然后把关键部分拿出来分析:
@Override
protected void configure(HttpSecurity http) throws Exception {
ResourceServerSecurityConfigurer resources = new ResourceServerSecurityConfigurer();
/* 省略部分代码 */
http.apply(resources);
/* 省略部分代码 */
}
以上的源码中,省略了两部分,第一部分在配置和应用一个 ResourceServerSecurityConfigurer 类型的配置对象,这是这个配置方法中最主要的部分,第二个省略的部分并不是重点。因此我们找到 ResourceServerSecurityConfigurer 类型的源码,分析其中的配置内容:
@Override
public void configure(HttpSecurity http) throws Exception {
AuthenticationManager oauthAuthenticationManager = oauthAuthenticationManager(http);
resourcesServerFilter = new OAuth2AuthenticationProcessingFilter();
resourcesServerFilter.setAuthenticationEntryPoint(authenticationEntryPoint);
resourcesServerFilter.setAuthenticationManager(oauthAuthenticationManager);
if (eventPublisher != null) {
resourcesServerFilter.setAuthenticationEventPublisher(eventPublisher);
}
if (tokenExtractor != null) {
resourcesServerFilter.setTokenExtractor(tokenExtractor);
}
if (authenticationDetailsSource != null) {
resourcesServerFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
}
resourcesServerFilter = postProcess(resourcesServerFilter);
resourcesServerFilter.setStateless(stateless);
// @formatter:off
http
.authorizeRequests().expressionHandler(expressionHandler)
.and()
.addFilterBefore(resourcesServerFilter, AbstractPreAuthenticatedProcessingFilter.class)
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler)
.authenticationEntryPoint(authenticationEntryPoint);
// @formatter:on
}
private AuthenticationManager oauthAuthenticationManager(HttpSecurity http) {
OAuth2AuthenticationManager oauthAuthenticationManager = new OAuth2AuthenticationManager();
if (authenticationManager != null) {
if (authenticationManager instanceof OAuth2AuthenticationManager) {
oauthAuthenticationManager = (OAuth2AuthenticationManager) authenticationManager;
}
else {
return authenticationManager;
}
}
oauthAuthenticationManager.setResourceId(resourceId);
oauthAuthenticationManager.setTokenServices(resourceTokenServices(http));
oauthAuthenticationManager.setClientDetailsService(clientDetails());
return oauthAuthenticationManager;
}
我们分析其中的内容:
- 代码第 4 行,方法开头,通过
oauthAuthenticationManager方法,创建了一个AuthenticationManager对象,从源码中可以看到,这个对象的实现类型是OAuth2AuthenticationManager。 - 代码第 5 行到第 18 行,创建并配置了
OAuth2AuthenticationProcessingFilter作为处理资源服务器认证流程的过滤器,上一步骤中创建的AuthenticationManager也会被配置给这个过滤器。并将这个过滤器添加到过滤器链上。
这篇源码分析到此为止,已经分析出了 @EnableResourceServer 注解所做的事情,其实就是在 Spring Security 的过滤器链里,增加了一个过滤器,对客户端对资源的访问请求进行拦截,然后校验其合法性。具体的认证过程,可以参考我的另一篇分析 Spring Security OAuth 资源服务器认证。
这里要顺便还要提两点:
- 之前的文章(Spring Security 认证流程 )中分析过的
ProviderManager类型,也是AuthenticationManager接口的实现类,通过authentication方法完成用户信息认证。因此,这里的OAuth2AuthenticationManager与其作用和原理相似。找到它们的共同点,有助于你理解其原理。 - 之前的另一篇文章(Spring Security OAuth 资源服务器认证 )曾提到了,资源服务器的过滤器
OAuth2AuthenticationProcessingFilter使用的authenticationManager类型是OAuth2AuthenticationManager,当时没有解释为什么是这个类,其实,它就是在这里配置的。想要了解资源服务器认证的具体过程,也可以去参考这篇文章。
这篇内容比较少,但是提到了一些与其他文章相重合或者相关联的地方,感兴趣的话,可以都读一读,可以帮助你完善自己的理解。