1. 前言
在上一篇Spring Security 实战干货:OAuth2 授权回调的核心认证流程中,我们讲了当第三方同意授权后会调用
redirectUri
发送回执给我们的服务器。我们的服务器拿到一个中间授信凭据会再次进行认证,目的是为了获取Token。而这个逻辑由
OAuth2LoginAuthenticationProvider
负责,经过上一文的分析后我们发现获取Token的具体逻辑由
OAuth2AuthorizationCodeAuthenticationProvider
来完成,今天就把它的流程搞清楚,来看看Spring Security OAuth2 认证授权获取Token的具体步骤。
❝
注意:本Spring Security干货系列教程的 OAuth2 相关部分是在Spring Security 5.x版本的。
2. OAuth2AuthorizationCodeAuthenticationProvider
该类是
AuthenticationProvider
针对OAuth 2.0中Authorization Code Grant模式的实现。关于
AuthenticationProvider
有必要简单强调一下,它已经多次在Spring Security 干货系列中出现,十分重要!一定要去看看相关的分析和使用,它是你根据业务扩展认证方式渠道的重要入口。
2.1 OAuth2AccessTokenResponseClient
在该实现中包含了一个
OAuth2AccessTokenResponseClient
成员变量,它抽象了通过
tokenUri
端点从认证服务器获取Token的细节。你可以根据OAuth 2.0常用的四种模式来进行实现它, 以达到根据不同的策略来获取Token的能力。
OAuth 2.0 四种模式的对应实现
在Spring Security 5中OAuth 2.0登录的配置中默认使用
DefaultAuthorizationCodeTokenResponseClient
。如果你想使用自定义实现的话可以通过
HttpSecurity
来配置:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.oauth2Login()
.tokenEndpoint()
// 注入自定义的 OAuth2AccessTokenResponseClient
.accessTokenResponseClient(authorizationCodeTokenResponseClient);
// 其它省略
}
接下来我们看看
DefaultAuthorizationCodeTokenResponseClient
实现的获取Token的逻辑:
@Override
public OAuth2AccessTokenResponse getTokenResponse(OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest) {
Assert.notNull(authorizationCodeGrantRequest, \"authorizationCodeGrantRequest cannot be null\");
// 1. 封装调用tokenUri所需要的请求参数RequestEntity
RequestEntity<?> request = this.requestEntityConverter.convert(authorizationCodeGrantRequest);
ResponseEntity<OAuth2AccessTokenResponse> response;
try {
// 2. 通过RestTemplate 发起请求获取 OAuth2AccessTokenResponse
response = this.restOperations.exchange(request, OAuth2AccessTokenResponse.class);
} catch (RestClientException ex) {
OAuth2Error oauth2Error = new OAuth2Error(INVALID_TOKEN_RESPONSE_ERROR_CODE,
\"An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: \" + ex.getMessage(), null);
throw new OAuth2AuthorizationException(oauth2Error, ex);
}
// 3. 解析 ResponseEntity 组织返回值 OAuth2AccessTokenResponse
OAuth2AccessTokenResponse tokenResponse = response.getBody();
if (CollectionUtils.isEmpty(tokenResponse.getAccessToken().getScopes())) {
// originally requested by the client in the Token Request
tokenResponse = OAuth2AccessTokenResponse.withResponse(tokenResponse)
.scopes(authorizationCodeGrantRequest.getClientRegistration().getScopes())
.build();
}
return tokenResponse;
}
这里的方式跟我另一个开源项目Payment Spring Boot的请求方式异曲同工,都是三个步骤:
- 组织参数
RequestEntity
。
-
RestOperations
发起请求。
- 解析
ResponseEntity
组织返回值。
如果有些的OAuth 2.0认证服务器获取Token的方式比较特殊你可以自行实现
OAuth2AccessTokenResponseClient
。
3. 总结
OAuth2AccessTokenResponseClient
是
OAuth2AuthorizationCodeAuthenticationProvider
的核心要点。搞清楚它的作用和机制就可以了。这里我们总结一下
OAuth2AuthorizationCodeAuthenticationProvider
的认证过程:
- 检测未授信
OAuth2AuthorizationCodeAuthenticationToken
的状态是否合法。
- 通过
OAuth2AccessTokenResponseClient
请求OAuth 2.0认证服务器获取Token等信息。
- 组装认证过的授信
OAuth2AuthorizationCodeAuthenticationToken
返回。
到此OAuth 2.0的登录流程就搞清楚了,读者可通过系列文章进行学习批判。