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