OAuth2TokenEndpointFilter
OAuth2TokenEndpointFilter是负责颁发token的过滤器。
AuthenticationConverter
负责将提交的参数转换为Authentication. 该属性的实例为DelegatingAuthenticationConverter, 是一个委派转换器,委派给下面的Convert执行
下面三个convert
0 = {OAuth2AuthorizationCodeAuthenticationConverter@7035}
1 = {OAuth2RefreshTokenAuthenticationConverter@7036}
2 = {OAuth2ClientCredentialsAuthenticationConverter@7037}
在构造方法中初始化的。
this.authenticationConverter = new DelegatingAuthenticationConverter(
Arrays.asList(
new OAuth2AuthorizationCodeAuthenticationConverter(),
new OAuth2RefreshTokenAuthenticationConverter(),
new OAuth2ClientCredentialsAuthenticationConverter())
);
Converter负责将请求信息转换为 Authentication
1. OAuth2ClientCredentialsAuthenticationConverter 得到的是 OAuth2ClientCredentialsAuthenticationToken.
2. OAuth2RefreshTokenAuthenticationConverter 得到的是 OAuth2RefreshTokenAuthenticationToken.
3. OAuth2AuthorizationCodeAuthenticationConverter 得到的是 OAuth2AuthorizationCodeAuthenticationToken.
AuthenticationManager
负责对Authentication进行认证。它的实例对象是ProviderManager,也是类似一个委派验证类。他让注册在他下面的AuthenticationManager依次去验证。
0 = {AnonymousAuthenticationProvider@7368}
1 = {OAuth2ClientAuthenticationProvider@7369}
2 = {OAuth2AuthorizationCodeRequestAuthenticationProvider@7370}
3 = {OAuth2AuthorizationCodeAuthenticationProvider@7371}
4 = {OAuth2RefreshTokenAuthenticationProvider@7372}
5 = {OAuth2ClientCredentialsAuthenticationProvider@7373}
6 = {OAuth2TokenRevocationAuthenticationProvider@7374}
7 = {OidcUserInfoAuthenticationProvider@7375}
8 = {OAuth2TokenIntrospectionAuthenticationProvider@7376}
9 = {JwtAuthenticationProvider@7377}
只是与上面的Converter不同的是,
converter是通过grant_type之类的来判断是否执行AuthenticationManager是直接调用supports方法来判断是否执行的.
if (!provider.supports(toTest)) {
continue;
}
该类在authentication
OAuth2ClientCredentialsAuthenticationProvider
客户端模式的AuthenticationManager为OAuth2ClientCredentialsAuthenticationProvider. 他验证的Authentication对象为OAuth2ClientCredentialsAuthenticationToken,验证成功后返回的Authentication对象为OAuth2AccessTokenAuthenticationToken. 这个里面没有再验证客户端信息,是因为在Converter得到OAuth2ClientCredentialsAuthenticationToken对象时就是从SecurityContextHolder中获取的。
Authentication clientPrincipal = SecurityContextHolder.getContext().getAuthentication();
....
return new OAuth2ClientCredentialsAuthenticationToken(
clientPrincipal,
requestedScopes,
additionalParameters
);
从上面的代码分析可以推测,在前面的filter中应该验证过.在里面把客户端的认证信息放进去的,中filter链中看最可能是应该是OAuth2ClientAuthenticationFilter。
0 = {WebAsyncManagerIntegrationFilter@7962}
1 = {SecurityContextPersistenceFilter@7963}
2 = {ProviderContextFilter@7964}
3 = {HeaderWriterFilter@7965}
4 = {LogoutFilter@7966}
5 = {OAuth2AuthorizationEndpointFilter@6806}
6 = {OidcProviderConfigurationEndpointFilter@7967}
7 = {NimbusJwkSetEndpointFilter@7968}
8 = {OAuth2AuthorizationServerMetadataEndpointFilter@7969}
9 = {OAuth2ClientAuthenticationFilter@7970}
10 = {UsernamePasswordAuthenticationFilter@7971}
11 = {DefaultLoginPageGeneratingFilter@6834}
12 = {DefaultLogoutPageGeneratingFilter@7972}
13 = {BearerTokenAuthenticationFilter@7973}
14 = {RequestCacheAwareFilter@7974}
15 = {SecurityContextHolderAwareRequestFilter@7975}
16 = {AnonymousAuthenticationFilter@7976}
17 = {SessionManagementFilter@7977}
18 = {ExceptionTranslationFilter@7978}
19 = {FilterSecurityInterceptor@7979}
20 = {OAuth2TokenEndpointFilter@6868}
21 = {OAuth2TokenRevocationEndpointFilter@7980}
22 = {OidcUserInfoEndpointFilter@7981}
23 = {OAuth2TokenIntrospectionEndpointFilter@7982}
OAuth2ClientAuthenticationFilter核心代码:
Authentication authenticationRequest = this.authenticationConverter.convert(request);
if (authenticationRequest instanceof AbstractAuthenticationToken) {
((AbstractAuthenticationToken) authenticationRequest).setDetails(
this.authenticationDetailsSource.buildDetails(request));
}
if (authenticationRequest != null) {
Authentication authenticationResult = this.authenticationManager.authenticate(authenticationRequest);
this.authenticationSuccessHandler.onAuthenticationSuccess(request, response, authenticationResult);
}
从头里面获取OAuth2ClientAuthenticationToken对象,OAuth2ClientAuthenticaitonProvider负责验证OAuth2ClientAuthenticationToken.
OAuth2ClientAuthenticaitonProvider校验的操作是通过RegisteredClientRepository去查询client信息然后比对密码等信息。
在onAuthenticationSuccess方法中将认证的客户端存储到SecurityContextHolder。
private void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
securityContext.setAuthentication(authentication);
SecurityContextHolder.setContext(securityContext);
}
从前面的分析可以知道OAuth2ClientCredentialsAuthenticationProvider其实已经把token颁发了,后续token能继续被使用那服务端一定有存储相应的token吗?
服务端会存颁发的token吗?
服务端会存储token。而负责存储token业务的操作在OAuth2AuthorizationService中,OAuth2AuthorizationService是一个接口,该接口存在两个对应的实现:
- InMemoryOAuthorizationService
- JdbcOAuth2AuthorizationService
一个是将token存在内存里面,另外一个将token存到数据库中.注入实现的时候如下:
static <B extends HttpSecurityBuilder<B>> OAuth2AuthorizationService getAuthorizationService(B builder) {
OAuth2AuthorizationService authorizationService = builder.getSharedObject(OAuth2AuthorizationService.class);
if (authorizationService == null) {
authorizationService = getOptionalBean(builder, OAuth2AuthorizationService.class);
if (authorizationService == null) {
authorizationService = new InMemoryOAuth2AuthorizationService();
}
builder.setSharedObject(OAuth2AuthorizationService.class, authorizationService);
}
return authorizationService;
}
所以希望自定义存储的位置,可以去实现OAuth2AuthorizationService,并且在SpringSecurity初始化配置的时候,设置到SharedObject中。
OAuth2ResourceOwnerPasswordAuthenticationProvider