spring-authorization-server令牌放發原始碼解析

冷冷發表於2022-06-14

Token 生成全流程

POST /auth/oauth2/token?grant_type=password&scope=server HTTP/1.1
Host: pig-gateway:9999
Authorization: Basic dGVzdDp0ZXN0
Content-Type: application/x-www-form-urlencoded
Content-Length: 32
username=admin&password=YehdBPev

⓪ 閘道器前置處理

驗證碼校驗 ValidateCodeGatewayFilter.java

參考資料: 驗證碼配置開關

前端已加密的密碼進行解密 PasswordDecoderFilter.java , 主要就是把如下圖的 password 密文轉成明文交由 SpringSecurity 處理

參考資料: 前端登入請求加密流程參考

① 客戶端認證處理

  • 如上圖在登入請求中會攜帶 Basic base64(clientId:clientSecret), 那麼首先OAuth2ClientAuthenticationFilter 會通過呼叫 RegisteredClientRepository (資料庫儲存) 來判斷傳入的客戶端是否正確

③ 正式接收登入請求

OAuth2TokenEndpointFilter 會接收通過上文 OAuth2ClientAuthenticationFilter 客戶端認證的請求

④ 組裝認證物件

AuthenticationConverter 會根據請求中的引數和授權型別組裝成對應的授權認證物件

⑤ 登入認證物件

public class XXXAuthenticationToken extends OAuth2ResourceOwnerBaseAuthenticationToken {

}

⑥ 授權認證呼叫

⑦ 核心認證邏輯

多使用者體系匹配 UserDetailsService

密碼匹配校驗

使用者狀態校驗

⑧ 使用者查詢邏輯

使用者查詢邏輯的多種實現形式

  • 解耦: 通過 feign 查詢其他系統獲取並組裝成 UserDetails
  • 簡單: 認證中心直接查詢 DB 並組裝成 UserDetails

⑨ 密碼校驗邏輯

預設支援加密方式如下:
{noop}密碼明文
{加密特徵碼}密碼密文
PasswordEncoder 會自動根據特徵碼匹配對應的加密演算法,所以上一步 ⑧ 查詢使用者物件組裝成 UserDetails 需要特殊處理
return new UserDetails(user.getUsername(),"{bcrypt}"+"資料庫儲存的密文");

⑩ 生成 OAuth2AccessToken

⑪ Token 儲存持久化

當前 SAS 僅支援 JDBC 和記憶體 ,PIG 擴充套件支援 Redis 實現

⑫ 登入成功事件處理

基於 SpringEvent 事件處理,可以在這裡做更多的處理 日誌、個性化等處理邏輯

⑬ 請求結果輸出 Token

private void sendAccessTokenResponse(HttpServletRequest request, HttpServletResponse response,
            Authentication authentication) throws IOException {

        OAuth2AccessTokenAuthenticationToken accessTokenAuthentication = (OAuth2AccessTokenAuthenticationToken) authentication;

        OAuth2AccessToken accessToken = accessTokenAuthentication.getAccessToken();
        OAuth2RefreshToken refreshToken = accessTokenAuthentication.getRefreshToken();
        Map<String, Object> additionalParameters = accessTokenAuthentication.getAdditionalParameters();
        // 無狀態 注意刪除 context 上下文的資訊
        SecurityContextHolder.clearContext();
        this.accessTokenHttpResponseConverter.write(accessTokenResponse, null, httpResponse);
    }
定義具體的輸出返回格式等邏輯

本文配套原始碼: https://github.com/pig-mesh/pig

相關文章