
在Spring Security 實戰干貨:客戶端OAuth2授權請求的入口中我們找到了攔截OAuth2授權請求入口/oauth2/authorization的過濾器OAuth2AuthorizationRequestRedirectFilter,并找到了真正發起OAuth2授權請求的方法sendRedirectForAuthorization,但是這個方法并沒有細說,所以今天接著上一篇把這個坑給補上,
2. sendRedirectForAuthorization
這個sendRedirectForAuthorization方法沒多少代碼,它的主要作用就是向第三方平臺進行授權重定向訪問,它所有的邏輯都和OAuth2AuthorizationRequest有關,因此我們對OAuth2AuthorizationRequest進行輕描淡寫是不行的,我們必須掌握OAuth2AuthorizationRequest是怎么來的,干嘛用的,
OAuth2AuthorizationRequestResolver
這就需要去分析決議類OAuth2AuthorizationRequestResolver,其核心方法有兩個多載,這里分析一個就夠了,
@Override
public OAuth2AuthorizationRequest resolve(HttpServletRequest request) {
// registrationId是通過uri路徑引數/oauth2/authorization/{registrationId}獲得的
String registrationId = this.resolveRegistrationId(request);
// 然后去請求物件request中提取key為action的引數,默認值是login
String redirectUriAction = getAction(request, "login");
// 然后進入根本的決議方法
return resolve(request, registrationId, redirectUriAction);
}
上面方法里面的resolve(request, registrationId, redirectUriAction)方法才是最終從/oauth2/authorization提取OAuth2AuthorizationRequest的根本方法,代碼太多但是我盡量通俗易懂的來進行圖解,resolve方法會根據不同的授權方式(AuthorizationGrantType)來組裝不同的OAuth2AuthorizationRequest,
3. OAuth2AuthorizationRequest
接下來就是OAuth2.0協議的核心重中之重了,可能以后你定制化的參考就來自這里,這是圈起來要考的知識點,我會對OAuth2AuthorizationRequestResolver在各種授權方式下的OAuth2AuthorizationRequest物件的決議進行一個完全的總結歸納,大致分為以下兩部分:
3.1 由AuthorizationGrantType決定的
在不同AuthorizationGrantType下對OAuth2AuthorizationRequest的梳理,涉及到的成員變數有:
authorizationGrantType,來自配置spring.security.client.registration.{registrationId}.authorizationGrantType,responseType, 由authorizationGrantType的值決定,參考下面的JSON,additionalParameters,當authorizationGrantType值為authorization_code時需要額外的一些引數,參考下面JSON ,attributes,不同的authorizationGrantType存在不同的屬性,
其中類似
{registrationId}的形式表示{registrationId}是一個變數,例如registrationId=gitee,
在OAuth2客戶端配置spring.security.client.registration.{registrationId}的前綴中有以下五種情況,
當 scope 不包含openid而且client-authentication-method不為none時上述四個引數:
{
"authorizationGrantType": "authorization_code",
"responseType": "code",
"additionalParameters": {},
"attributes": {
"registration_id": "{registrationId}"
}
}
當 scope 包含openid而且client-authentication-method不為none時上述四個引數:
{
"authorizationGrantType": "authorization_code",
"responseType": "code",
"additionalParameters": {
"nonce": "{nonce}的Hash值"
},
"attributes": {
"registration_id": "{registrationId}",
"nonce": "{nonce}"
}
}
當 scope不包含openid而且client-authentication-method為none時上述四個引數:
{
"authorizationGrantType": "authorization_code",
"responseType": "code",
"additionalParameters": {
"code_challenge": "{codeVerifier}的Hash值",
// code_challenge_method 當不是SHA256可能沒有該key
"code_challenge_method": "S256(如果是SHA256演算法的話)"
},
"attributes": {
"registration_id": "{registrationId}",
"code_verifier": "Base64生成的安全{codeVerifier}"
}
}
當 scope包含openid而且client-authentication-method為none時上述四個引數:
{
"authorizationGrantType": "authorization_code",
"responseType": "code",
"additionalParameters": {
"code_challenge": "{codeVerifier}的Hash值",
// code_challenge_method 當不是SHA256可能沒有該key
"code_challenge_method": "S256(如果是SHA256演算法的話)",
"nonce": "{nonce}的Hash值"
},
"attributes": {
"registration_id": "{registrationId}",
"code_verifier": "Base64生成的安全{codeVerifier}",
"nonce": "{nonce}"
}
}
implicit下要簡單的多:
{
"authorizationGrantType": "implicit",
"responseType": "token",
"attributes": {}
}
3.2 固定規則部分
上面是各種不同AuthorizationGrantType下的OAuth2AuthorizationRequest的成員變數個性化取值策略, 還有幾個引數的規則是固定的:
clientId來自于配置,是第三方平臺給予我們的唯一標識,authorizationUri來自于配置,用來構造向第三方發起的請求URL,scopes來自于配置,是第三方平臺給我們授權劃定的作用域,可以理解為角色,state自動生成的,為了防止csrf 攻擊,authorizationRequestUri向第三方平臺發起授權請求的,可以直接通過OAuth2AuthorizationRequest的構建類來設定或者通過上面的authorizationUri等引數來生成,稍后會把構造機制分析一波,redirectUri當OAuth2AuthorizationRequest被第三方平臺收到后,第三方平臺會回呼這個URI來對授權請求進行相應,稍后也會來分析其機制,
authorizationRequestUri的構建機制
如果不顯式提供authorizationRequestUri就會通過OAuth2AuthorizationRequest中的
responseTypeclientIdscopesstateredirectUriadditionalParameters
按照下面的規則進行拼接成authorizationUri的引數串,引數串的key和value都要進行URI編碼,
authorizationUri?response_type={responseType.getValue()}&client_id={clientId}&scope={scopes元素一個字符間隔}&state={state}&redirect_uri={redirectUri}&{additionalParameter展開進行同樣規則的KV引數串}
然后OAuth2AuthorizationRequestRedirectFilter負責重定向到authorizationRequestUri向第三方請求授權,
redirectUri
第三方收到回應會呼叫redirectUri,回呼也是有一定默認規則的,它遵循{baseUrl}/{action}/oauth2/code/{registrationId}的路徑引數規則,
baseUrl是從我們/oauth2/authorization請求中提取的基礎請求路徑,action,有兩種默認值login、authorize,當/oauth2/authorization請求中包含了action引數時會根據action的值進行填充,registrationId這個就不用多說了,
4. 總結
通過對OAuth2AuthorizationRequest請求物件的規則進行詳細分析,我們應該能大致的知道的過濾器OAuth2AuthorizationRequestRedirectFilter流程:
- 通過客戶端配置構建
ClientRegistration,后續可以進行持久化, - 攔截
/oauth2/authorization請求并構造OAuth2AuthorizationRequest,然后重定向到authorizationRequestUri進行請求授權, - 第三方通過
redirect_uri進行相應,
那么Spring Security OAuth2如何對第三方的回呼相應進行處理呢?關注:碼農小胖哥 為你揭曉這個答案,
關注公眾號:Felordcn 獲取更多資訊
個人博客:https://felord.cn
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/210503.html
標籤:Java
下一篇:java基礎基礎知識點總結
