自定義Feign攔截器,解決微服務之間Feign調用請求頭丟失問題


在微服務開發過程中,安全方面使用的是Spring Security OAuth2.0令牌認證,在進行服務與服務之間調用時,使用的Feign客戶端,如果不通過Feign攔截器來添加請求頭信息。下游服務是接收不到認證過的token令牌,無法進行身份驗證。

  1. 定義Feign攔截器,實現 RequestInterceptor 接口

    @Slf4j
    public class FeignRequestInterceptor implements RequestInterceptor {
        /**
         * 微服務之間傳遞的唯一標識
         */
        public static final String X_REQUEST_ID = "X-Request-Id";
    
        @Override
        public void apply(RequestTemplate template) {
    
            HttpServletRequest httpServletRequest = getHttpServletRequest();
    
            if (httpServletRequest != null) {
                //獲取頭信息
                Map<String, String> headers = getHeaders(httpServletRequest);
                // 傳遞所有請求頭,防止部分丟失
                Iterator<Map.Entry<String, String>> iterator = headers.entrySet().iterator();
    
                //將請求的頭信息放入到RequestTemplate 的頭信息中,當使用RequestTemplate發起請求時會自動添加頭信息
                while (iterator.hasNext()) {
                    Map.Entry<String, String> entry = iterator.next();
                    template.header(entry.getKey(), entry.getValue());
                }
                // 微服務之間傳遞的唯一標識,區分大小寫所以通過httpServletRequest獲取
                if (httpServletRequest.getHeader(X_REQUEST_ID) == null) {
                    String sid = String.valueOf(UUID.randomUUID());
                    template.header(X_REQUEST_ID, sid);
                }
                log.debug("FeignRequestInterceptor:{}", template.toString());
            }
        }
    
        /**
         * RequestContextHolder 中獲取 HttpServletRequest對象
         *
         * @return
         */
        private HttpServletRequest getHttpServletRequest() {
            try {
                return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            } catch (Exception e) {
                return null;
            }
        }
    
        /**
         * 獲取頭信息
         *
         * @param request
         * @return
         */
        private Map<String, String> getHeaders(HttpServletRequest request) {
            Map<String, String> map = new LinkedHashMap<>();
            Enumeration<String> enumeration = request.getHeaderNames();
            if (enumeration != null) {
                while (enumeration.hasMoreElements()) {
                    String key = enumeration.nextElement();
                    String value = request.getHeader(key);
                    map.put(key, value);
                }
            }
            return map;
        }
    
    }
    
  2. 配置Bean

    @Bean
        @ConditionalOnMissingBean(FeignRequestInterceptor.class)
        public RequestInterceptor feignRequestInterceptor() {
    
            FeignRequestInterceptor interceptor = new FeignRequestInterceptor();
            log.info("FeignRequestInterceptor [{}]", interceptor);
            return interceptor;
        }
    

    在每次進行調用時,會經過 OAuth2AuthenticationProcessingFilter 過濾器的 doFilter方法進行token驗證,通過 tokenExtract 的 extract 方法抽取攜帶在請求中的令牌信息。

  3. OAuth2AuthenticationProcessingFilter 的 doFilter
    在這里插入圖片描述

    如果認證成功,放入SpringContext上下文中

    在這里插入圖片描述


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM