成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Spring Cloud實戰小貼士:Zuul處理Cookie和重定向

開發 開發工具
由于我們在之前所有的入門教程中,對于HTTP請求都采用了簡單的接口實現。而實際使用過程中,我們的HTTP請求要復雜的多,本文主要分析HTTP請求時遇見的常見問題以及解決方法。

由于我們在之前所有的入門教程中,對于HTTP請求都采用了簡單的接口實現。而實際使用過程中,我們的HTTP請求要復雜的多,比如當我們將Spring Cloud Zuul作為API網關接入網站類應用時,往往都會碰到下面這兩個非常常見的問題:

  • 會話無法保持
  • 重定向后的HOST錯誤

本文將幫助大家分析問題原因并給出解決這兩個常見問題的方法。

[[190127]]

一、會話保持問題

通過跟蹤一個HTTP請求經過Zuul到具體服務,再到返回結果的全過程。我們很容易就能發現,在傳遞的過程中,HTTP請求頭信息中的Cookie和Authorization都沒有被正確地傳遞給具體服務,所以最終導致會話狀態沒有得到保持的現象。

那么這些信息是在哪里丟失的呢?我們從Zuul進行路由轉發的過濾器作為起點,來一探究竟。下面是RibbonRoutingFilter過濾器的實現片段:

  1. public class RibbonRoutingFilter extends ZuulFilter{ 
  2.     ... 
  3.     protected ProxyRequestHelper helper; 
  4.      
  5.     @Override 
  6.     public Object run() { 
  7.         RequestContext context = RequestContext.getCurrentContext(); 
  8.         this.helper.addIgnoredHeaders(); 
  9.         try { 
  10.             RibbonCommandContext commandContext = buildCommandContext(context); 
  11.             ClientHttpResponse response = forward(commandContext); 
  12.             setResponse(response); 
  13.             return response; 
  14.         } 
  15.         ... 
  16.         return null; 
  17.     } 
  18.      
  19.         protected RibbonCommandContext buildCommandContext(RequestContext context) { 
  20.         HttpServletRequest request = context.getRequest(); 
  21.         MultiValueMap<String, String> headers = this.helper 
  22.                 .buildZuulRequestHeaders(request); 
  23.         MultiValueMap<String, String> params = this.helper 
  24.                 .buildZuulRequestQueryParams(request); 
  25.         ... 
  26.     } 

這里有三個重要元素:

  • 過濾器的核心邏輯run函數實現,其中調用了內部函數buildCommandContext來構建上下文內容
  • 而buildCommandContext中調用了helper對象的buildZuulRequestHeaders方法來處理請求頭信息
  • helper對象是ProxyRequestHelper類的實例

接下來我們再看看ProxyRequestHelper的實現:

  1. public class ProxyRequestHelper { 
  2.     public MultiValueMap<String, String> buildZuulRequestHeaders( 
  3.             HttpServletRequest request) { 
  4.         RequestContext context = RequestContext.getCurrentContext(); 
  5.         MultiValueMap<String, String> headers = new HttpHeaders(); 
  6.         Enumeration<String> headerNames = request.getHeaderNames(); 
  7.         if (headerNames != null) { 
  8.             while (headerNames.hasMoreElements()) { 
  9.                 String name = headerNames.nextElement(); 
  10.                 if (isIncludedHeader(name)) { 
  11.                     Enumeration<String> values = request.getHeaders(name); 
  12.                     while (values.hasMoreElements()) { 
  13.                         String value = values.nextElement(); 
  14.                         headers.add(name, value); 
  15.                     } 
  16.                 } 
  17.             } 
  18.         } 
  19.         Map<String, String> zuulRequestHeaders = context.getZuulRequestHeaders(); 
  20.         for (String header : zuulRequestHeaders.keySet()) { 
  21.             headers.set(header, zuulRequestHeaders.get(header)); 
  22.         } 
  23.         headers.set(HttpHeaders.ACCEPT_ENCODING, "gzip"); 
  24.         return headers; 
  25.     } 
  26.     public boolean isIncludedHeader(String headerName) { 
  27.         String name = headerName.toLowerCase(); 
  28.         RequestContext ctx = RequestContext.getCurrentContext(); 
  29.         if (ctx.containsKey(IGNORED_HEADERS)) { 
  30.             Object object = ctx.get(IGNORED_HEADERS); 
  31.             if (object instanceof Collection && ((Collection<?>) object).contains(name)) { 
  32.                 return false; 
  33.             } 
  34.         } 
  35.         ... 
  36.     } 

從上述源碼中,我們可以看到構建頭信息的方法buildZuulRequestHeaders通過isIncludedHeader函數來判斷當前請求的各個頭信息是否在忽略的頭信息清單中,如果是的話就不組織到此次轉發的請求中去。那么這些需要忽略的頭信息是在哪里初始化的呢?在PRE階段的PreDecorationFilter過濾器中,我們可以找到答案:

  1. public class PreDecorationFilter extends ZuulFilter{ 
  2.     ... 
  3.     public Object run() { 
  4.         RequestContext ctx = RequestContext.getCurrentContext(); 
  5.         final String requestURI = this.urlPathHelper.getPathWithinApplication(ctx.getRequest()); 
  6.         Route route = this.routeLocator.getMatchingRoute(requestURI); 
  7.         if (route != null) { 
  8.             String location = route.getLocation(); 
  9.             if (location != null) { 
  10.                 ctx.put("requestURI", route.getPath()); 
  11.                 ctx.put("proxy", route.getId()); 
  12.                 // 處理忽略頭信息的部分 
  13.                 if (!route.isCustomSensitiveHeaders()) { 
  14.                     this.proxyRequestHelper.addIgnoredHeaders( 
  15.                         this.properties.getSensitiveHeaders() 
  16.                         .toArray(new String[0])); 
  17.                 } else { 
  18.                     this.proxyRequestHelper.addIgnoredHeaders( 
  19.                         route.getSensitiveHeaders() 
  20.                         .toArray(new String[0])); 
  21.                 } 
  22.         ... 

從上述源碼中,我們可以看到有一段if/else塊,通過調用ProxyRequestHelper的addIgnoredHeaders方法來添加需要忽略的信息到請求上下文中,供后續ROUTE階段的過濾器使用。這里的if/else塊分別用來處理全局設置的敏感頭信息和指定路由設置的敏感頭信息。而全局的敏感頭信息定義于ZuulProperties中:

  1. @Data 
  2. @ConfigurationProperties("zuul") 
  3. public class ZuulProperties{ 
  4.     private Set<String> sensitiveHeaders = new LinkedHashSet<>
  5.             Arrays.asList("Cookie", "Set-Cookie", "Authorization")); 
  6.     ... 

所以解決該問題的思路也很簡單,我們只需要通過設置sensitiveHeaders即可,設置方法分為兩種:

1. 全局設置:

  • zuul.sensitive-headers=

2. 指定路由設置:

  • zuul.routes..sensitive-headers=
  • zuul.routes..custom-sensitive-headers=true

二、重定向問題

在使用Spring Cloud Zuul對接Web網站的時候,處理完了會話控制問題之后。往往我們還會碰到如下圖所示的問題,我們在瀏覽器中通過Zuul發起了登錄請求,該請求會被路由到某WebSite服務,該服務在完成了登錄處理之后,會進行重定向到某個主頁或歡迎頁面。此時,仔細的開發者會發現,在登錄完成之后,我們瀏覽器中URL的HOST部分發生的改變,該地址變成了具體WebSite服務的地址了。這就是在這一節,我們將分析和解決的重定向問題!

Spring Cloud Zuul對接Web網站

出現該問題的根源是Spring Cloud Zuul沒有正確的處理HTTP請求頭信息中的Host導致。在Brixton版本中,Spring Cloud Zuul的PreDecorationFilter過濾器實現時完全沒有考慮這一問題,它更多的定位于REST API的網關。所以如果要在Brixton版本中增加這一特性就相對較為復雜,不過好在Camden版本之后,Spring Cloud Netflix 1.2.x版本的Zuul增強了該功能,我們只需要通過配置屬性zuul.add-host-header=true就能讓原本有問題的重定向操作得到正確的處理。關于更多Host頭信息的處理,讀者可以參考本文之前的分析思路,可以通過查看PreDecorationFilter過濾器的源碼來詳細更多實現細節。

【本文為51CTO專欄作者“翟永超”的原創稿件,轉載請通過51CTO聯系作者獲取授權】

 

戳這里,看該作者更多好文

責任編輯:趙寧寧 來源: 51CTO專欄
相關推薦

2017-05-18 14:14:25

過濾器Spring ClouZuul

2017-05-19 15:13:05

過濾器Spring ClouZuul

2017-07-31 15:47:50

Zuul統一處理

2017-10-20 14:55:06

Spring ClouZuul加載

2017-10-18 16:00:14

SpringCloudZuul路徑

2017-08-10 16:14:07

FeignRPC模式

2017-09-26 16:17:39

Ribboneager-load模式

2010-12-14 15:07:15

ICMP路由重定向

2017-04-12 14:43:01

Spring ClouZuul過濾器

2024-08-05 10:03:53

2010-07-13 14:10:44

ICMP協議

2017-04-13 11:06:28

SpringCloud隨機端口

2017-05-04 22:30:17

Zuul過濾器微服務

2021-04-20 10:15:34

Spring ClouZuul架構

2009-06-25 14:54:22

Servlet轉發Servlet重定向

2024-12-20 07:30:00

重定向服務器端指令Next.js

2022-11-10 15:08:44

Linux輸入輸出

2010-08-17 11:35:00

2010-12-31 13:35:25

文件夾重定向

2020-07-27 07:41:23

Linux重定向數據流
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 成人精品久久 | 亚洲一级毛片 | 完全免费在线视频 | 亚洲精品国产综合区久久久久久久 | 久久成人av电影 | 91精品国产色综合久久不卡98口 | 免费激情av| 五月婷婷色| 日韩激情一区 | 99资源站 | 亚洲成人免费视频在线 | 成人a视频 | 毛片链接 | 国产精品免费大片 | 一区二区三区视频在线观看 | 伊人国产精品 | 亚洲午夜在线 | 国产剧情一区 | 亚洲第一在线视频 | 亚洲精品一区二区三区免 | av无遮挡| 亚洲高清视频一区 | 日韩中文字幕第一页 | 久久精品免费观看 | 黄色毛片在线观看 | 欧美在线一区二区三区 | 国产区视频在线观看 | 91久久精品国产91久久 | 欧美a区 | 精品一区二区三区在线观看国产 | 青青草华人在线视频 | 欧美888| 一区二区三区四区在线视频 | 日本a∨视频| 亚洲综合天堂 | 欧美精品久久久久 | 精品无码久久久久久国产 | 一区二区不卡 | 久久久亚洲一区 | 成人午夜免费在线视频 | 久久久蜜臀国产一区二区 |