1.客戶端攜帶認證中心發放的token,請求資源服務器A(Spring Security OAuth 發放Token 源碼解析)git
2.客戶端攜帶令牌直接訪問資源服務器,資源服務器經過對token 的校驗 (Spring Cloud OAuth2 資源服務器CheckToken 源碼解析 ) 判斷用戶的合法性,並保存到上下文中spring
3.A服務接口接收到請求,須要經過Feign或者其餘RPC框架調用B服務來組裝返回數據安全
本文主要來探討第三部 A --> B ,token 自定維護的源碼實現服務器
@Bean @ConditionalOnProperty("security.oauth2.client.client-id") public RequestInterceptor oauth2FeignRequestInterceptor(OAuth2ClientContext oAuth2ClientContext, OAuth2ProtectedResourceDetails resource,) { return new OAuth2FeignRequestInterceptor(oAuth2ClientContext, resource); }
public class OAuth2FeignRequestInterceptor implements RequestInterceptor { // 給請求增長 token @Override public void apply(RequestTemplate template) { template.header(header, extract(tokenType)); } protected String extract(String tokenType) { OAuth2AccessToken accessToken = getToken(); return String.format("%s %s", tokenType, accessToken.getValue()); } // 從spring security 上下文中獲取token public OAuth2AccessToken getToken() { OAuth2AccessToken accessToken = oAuth2ClientContext.getAccessToken(); if (accessToken == null || accessToken.isExpired()) { try { accessToken = acquireAccessToken(); } } return accessToken; } }
public class AccessTokenContextRelay { private OAuth2ClientContext context; public AccessTokenContextRelay(OAuth2ClientContext context) { this.context = context; } public boolean copyToken() { if (context.getAccessToken() == null) { Authentication authentication = SecurityContextHolder.getContext() .getAuthentication(); if (authentication != null) { Object details = authentication.getDetails(); if (details instanceof OAuth2AuthenticationDetails) { OAuth2AuthenticationDetails holder = (OAuth2AuthenticationDetails) details; String token = holder.getTokenValue(); DefaultOAuth2AccessToken accessToken = new DefaultOAuth2AccessToken( token); String tokenType = holder.getTokenType(); if (tokenType != null) { accessToken.setTokenType(tokenType); } context.setAccessToken(accessToken); return true; } } } return false; } }
源碼很是簡單app
這三個問題,你們在使用的過程當中必定會遇到框架
public void apply(RequestTemplate template) { Collection<String> fromHeader = template.headers().get(SecurityConstants.FROM); if (CollUtil.isNotEmpty(fromHeader) && fromHeader.contains(SecurityConstants.FROM_IN)) { return; } accessTokenContextRelay.copyToken(); if (oAuth2ClientContext != null && oAuth2ClientContext.getAccessToken() != null) { super.apply(template); } }
歡迎關注咱們得到更多的好玩JavaEE 實踐ide