Spring Authorization Server OAuth2TokenEndpointFilter源码分析

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不同的是,

  1. converter是通过grant_type之类的来判断是否执行
  2. AuthenticationManager是直接调用supports方法来判断是否执行的.
if (!provider.supports(toTest)) {
	continue;
}

该类在authentication

OAuth2ClientCredentialsAuthenticationProvider

客户端模式的AuthenticationManagerOAuth2ClientCredentialsAuthenticationProvider. 他验证的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是一个接口,该接口存在两个对应的实现:

  1. InMemoryOAuthorizationService
  2. 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

你可能感兴趣的:(spring)