Spring Security 實戰乾貨:客戶端OAuth2授權請求的
1. 前言
在[Spring Security 實戰乾貨:OAuth2第三方授權初體驗]一文中我先對OAuth2.0涉及的一些常用概念進行介紹,然後直接透過一個DEMO來讓大家切身感受了OAuth2.0第三方授權功能。今天我們來一步一步分析這其中的機制。
2. 抓住源頭
>
上面這個請求URL是我們在[上一篇]文章中提到的客戶端進行第三方認證操作的起點,預設格式為{baseUrl}/oauth2/authorization/{clientRegistrationId}
,其中clientRegistrationId
代表著一個第三方標識,可以是微信、支付寶等開放平臺,這裡為gitee
。使用者點選了這個請求後就開始了授權之旅。假如大家都是從零開始的小白,肯定是要從這個入口來一步一步探尋其中的機制的。Spring Security一定是攔截到了/oauth2/authorization
後才啟用了OAuth2相關的處理邏輯。那就去抓住這個源頭!從原始碼中搜尋嘛!IDEA 快捷鍵CTRL SHIFT R
就可以全域性搜尋結果了。
不出所料找到了三個地方,記下來一個一個看!
OAuth2AuthorizationRequestRedirectWebFilter
先來看第一個OAuth2AuthorizationRequestRedirectWebFilter
,它實現了Spring Webflux的WebFilter
介面,這顯然是Webflux的東西,如果你用到Webflux的話這個會有用,但是不是現在我們用的。
DefaultOAuth2AuthorizationRequestResolver
第二個是幹嘛的呢,從名稱上看著是一個預設OAuth2授權請求解析器。有時候名稱起的好就知道這個東西大致上幹嘛的,不得不說優秀框架細節抓的很好。它實現了介面OAuth2AuthorizationRequestResolver
:
public interface OAuth2AuthorizationRequestResolver {
/**
* 從HttpServletRequest物件中解析封裝 OAuth2AuthorizationRequest
*/
OAuth2AuthorizationRequest resolve(HttpServletRequest request);
/**
* 從HttpServletRequest物件以及clientRegistrationId中解析封裝 OAuth2AuthorizationRequest
*/
OAuth2AuthorizationRequest resolve(HttpServletRequest request, String clientRegistrationId);
}
也就是說當我們請求/oauth2/authorization
時,DefaultOAuth2AuthorizationRequestResolver
會從/oauth2/authorization
對應的HttpServletRequest
中提取資料封裝到OAuth2AuthorizationRequest
請求物件中做進一步使用。
> 注意:/oauth2/authorization
這個預設攔截標識也是可以自定義的。
OAuth2AuthorizationRequest
這裡簡單提一下OAuth2AuthorizationRequest
封裝了我們上一文所描述的一些OAuth2相關概念引數,後續這個請求類我們會用到它。
public final class OAuth2AuthorizationRequest implements Serializable {
private static final long serialVersionUID = 520L;
private String authorizationUri;
private AuthorizationGrantType authorizationGrantType;
private OAuth2AuthorizationResponseType responseType;
private String clientId;
private String redirectUri;
private Set scopes;
private String state;
private Map additionalParameters;
private String authorizationRequestUri;
private Map attributes;
// 其它方法略
}
OAuth2AuthorizationRequestRedirectFilter
就剩下這個線索了,一看到它繼承了OncePerRequestFilter
我就知道肯定是他了。甚至它的成員變數包含了用來解析OAuth2請求的OAuth2AuthorizationRequestResolver
。到這裡我們的路子就走對了,開始分析這個過濾器,下面是其核心過濾邏輯,這就是我們想要知道的OAuth2授權請求是如何被攔截處理的邏輯。
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
try {
OAuth2AuthorizationRequest authorizationRequest = this.authorizationRequestResolver.resolve(request);
if (authorizationRequest != null) {
this.sendRedirectForAuthorization(request, response, authorizationRequest);
return;
}
} catch (Exception failed) {
this.unsuccessfulRedirectForAuthorization(request, response, failed);
return;
}
try {
filterChain.doFilter(request, response);
} catch (IOException ex) {
throw ex;
} catch (Exception ex) {
// Check to see if we need to handle ClientAuthorizationRequiredException
Throwable[] causeChain = this.throwableAnalyzer.determineCauseChain(ex);
ClientAuthorizationRequiredException authzEx = (ClientAuthorizationRequiredException) this.throwableAnalyzer
.getFirstThrowableOfType(ClientAuthorizationRequiredException.class, causeChain);
if (authzEx != null) {
try {
OAuth2AuthorizationRequest authorizationRequest = this.authorizationRequestResolver.resolve(request, authzEx.getClientRegistrationId());
if (authorizationRequest == null) {
throw authzEx;
}
this.sendRedirectForAuthorization(request, response, authorizationRequest);
this.requestCache.saveRequest(request, response);
} catch (Exception failed) {
this.unsuccessfulRedirectForAuthorization(request, response, failed);
}
return;
}
if (ex instanceof ServletException) {
throw (ServletException) ex;
} else if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
} else {
throw new RuntimeException(ex);
}
}
}
doFilterInternal
對應的流程如下:
根據這個流程,如果要搞清楚Spring Security OAuth2是如何重定向到第三方的話就要深入研究sendRedirectForAuthorization
方法,基於篇幅原因我會在下一篇進行分析。
3. 總結
今天我們從源頭一步一步找到OAuth2授權的處理入口,並初步分析了幾個關鍵元件的作用以及核心攔截器的攔截邏輯。後續我們將層層深入循序漸進地搞清楚其運作流程,不要走開,鎖定:碼農小胖哥 循序漸進學習Spring Security OAuth2 。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/3549/viewspace-2826850/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Spring Security 實戰乾貨:客戶端OAuth2授權請求的入口Spring客戶端OAuth
- Spring Security 實戰乾貨:OAuth2授權請求是如何構建並執行的SpringOAuth
- Spring Security 實戰乾貨:OAuth2第三方授權初體驗SpringOAuth
- spring security oauth2 password授權模式SpringOAuth模式
- Spring Security 實戰乾貨:理解AuthenticationManagerSpring
- Spring Security 實戰乾貨:OAuth2登入獲取Token的核心邏輯SpringOAuth
- Spring Boot Security OAuth2 實現支援JWT令牌的授權伺服器Spring BootOAuthJWT伺服器
- Spring Security 實戰乾貨:分散式物件SharedObjectSpring分散式物件Object
- Spring Security如何優雅的增加OAuth2協議授權模式SpringOAuth協議模式
- Spring Security 實戰乾貨:AuthenticationManager的初始化細節Spring
- Spring Security 實戰乾貨:實現自定義退出登入Spring
- Spring Security 實戰乾貨:圖解Spring Security中的Servlet過濾器體系Spring圖解Servlet過濾器
- Spring Security 實戰乾貨:玩轉自定義登入Spring
- 【認證與授權】Spring Security的授權流程Spring
- nginx截獲客戶端請求Nginx客戶端
- Spring Security 實戰乾貨:使用 JWT 認證訪問介面SpringJWT
- Java OAuth 2.0 客戶端程式設計(二): 客戶端憑據授權JavaOAuth客戶端程式設計
- Spring Security 實戰乾貨:如何實現不同的介面不同的安全策略Spring
- [譯] 在 GO 語言中建立你自己的 OAuth2 服務:客戶端憑據授權流程GoOAuth客戶端
- flutter開發的乾貨集中營客戶端Flutter客戶端
- Spring Security中實現微信網頁授權Spring網頁
- 使用Spring Security OAuth 實現OAuth 2.0 授權SpringOAuth
- Spring Security 實戰乾貨:基於配置的介面角色訪問控制Spring
- Spring Security原始碼分析二:Spring Security授權過程Spring原始碼
- Spring Security 實戰乾貨:基於註解的介面角色訪問控制Spring
- Spring Security OAuth2.0認證授權六:前後端分離下的登入授權SpringOAuth後端
- OAuth 2.0 授權碼請求OAuth
- nginx 處理客戶端請求的完整過程Nginx客戶端
- 乾貨!無需任何工具,實測macOS雙開微信客戶端Mac客戶端
- 實踐乾貨!猿題庫 iOS 客戶端架構設計iOS客戶端架構
- Oauth2(2)客戶端註冊OAuth客戶端
- 服務端如何獲取客戶端請求IP地址服務端客戶端
- Spring Cloud實戰 | 最終篇:Spring Cloud Gateway+Spring Security OAuth2整合統一認證授權平臺下實現登出使JWT失效方案SpringCloudGatewayOAuthJWT
- Spring Security Oauth2SpringOAuth
- IdentityServer4 (1) 客戶端授權模式(Client Credentials)IDEServer客戶端模式client
- Spring Security 實戰乾貨:從零手寫一個驗證碼登入Spring
- Spring Security系列之授權過程(七)Spring
- 從客戶端向服務端發起請求(3種)客戶端服務端