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的能力。
在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的登入流程就搞清楚了,讀者可通過系列文章進行學習批判。我是:碼農小胖哥,多多關注,獲取實用的程式設計乾貨。
關注公眾號:Felordcn 獲取更多資訊