Token 必定要放在請求頭中嗎? 答案確定是否認的,本文將從源碼的角度來分享一下 spring security oauth2 的解析過程,及其擴展點的應用場景。java
當咱們使用 spring security oauth2 時, 通常狀況下須要把認證中心申請的 token 放在請求頭中請求目標接口,以下圖 ①git
spring security oauth2 經過攔截器獲取此 token 完成令牌到當前用戶信息(UserDetails)的轉換。spring
public class OAuth2AuthenticationProcessingFilter{ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { try { // 1. 根據用戶請求解析令牌,組裝預登錄對象 Authentication authentication = tokenExtractor.extract(request); if (authentication == null) { // 如果預登錄狀態爲空,把無狀態登陸清空 if (stateless && isAuthenticated()) { SecurityContextHolder.clearContext(); } } else { // 2. 根據token 來作真正的認證登陸 Provier Authentication authResult = authenticationManager.authenticate(authentication); // 3. 登陸成功邏輯 eventPublisher.publishAuthenticationSuccess(authResult); SecurityContextHolder.getContext().setAuthentication(authResult); } } catch (OAuth2Exception failed) { // 異常通知邏輯 Spring Event ... return; } chain.doFilter(request, response); } }
咱們主要來關注第一步 根據用戶請求解析令牌,組裝預登錄對象less
來看默認實現 BearerTokenExtractoride
public class BearerTokenExtractor implements TokenExtractor { @Override public Authentication extract(HttpServletRequest request) { // 1. 解析token String tokenValue = extractToken(request); if (tokenValue != null) { // 2. 建立一個authentication 返回 PreAuthenticatedAuthenticationToken authentication = new PreAuthenticatedAuthenticationToken(tokenValue, ""); return authentication; } return null; } protected String extractToken(HttpServletRequest request) { // 1.1 優先從請求header 獲取token String token = extractHeaderToken(request); // 1.2 如果請求token 中沒有,則獲取請求參數中的 access_token 參數 if (token == null) { token = request.getParameter(OAuth2AccessToken.ACCESS_TOKEN); } return token; } }
以上源碼參考: 基於 Spring Boot 2.3.0、 Spring Cloud Hoxton & Alibaba、 OAuth2 的 RBAC 權限管理系統 PigBearerTokenExtractor 部分擴展code
項目推薦: Spring Cloud 、Spring Security OAuth2的RBAC權限管理系統 歡迎關注component