自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Spring Cloud實(shí)戰(zhàn)小貼士:Zuul處理Cookie和重定向

開發(fā) 開發(fā)工具
由于我們?cè)谥八械娜腴T教程中,對(duì)于HTTP請(qǐng)求都采用了簡(jiǎn)單的接口實(shí)現(xiàn)。而實(shí)際使用過程中,我們的HTTP請(qǐng)求要復(fù)雜的多,本文主要分析HTTP請(qǐng)求時(shí)遇見的常見問題以及解決方法。

由于我們?cè)谥八械娜腴T教程中,對(duì)于HTTP請(qǐng)求都采用了簡(jiǎn)單的接口實(shí)現(xiàn)。而實(shí)際使用過程中,我們的HTTP請(qǐng)求要復(fù)雜的多,比如當(dāng)我們將Spring Cloud Zuul作為API網(wǎng)關(guān)接入網(wǎng)站類應(yīng)用時(shí),往往都會(huì)碰到下面這兩個(gè)非常常見的問題:

  • 會(huì)話無法保持
  • 重定向后的HOST錯(cuò)誤

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

[[190127]]

一、會(huì)話保持問題

通過跟蹤一個(gè)HTTP請(qǐng)求經(jīng)過Zuul到具體服務(wù),再到返回結(jié)果的全過程。我們很容易就能發(fā)現(xiàn),在傳遞的過程中,HTTP請(qǐng)求頭信息中的Cookie和Authorization都沒有被正確地傳遞給具體服務(wù),所以最終導(dǎo)致會(huì)話狀態(tài)沒有得到保持的現(xiàn)象。

那么這些信息是在哪里丟失的呢?我們從Zuul進(jìn)行路由轉(zhuǎn)發(fā)的過濾器作為起點(diǎn),來一探究竟。下面是RibbonRoutingFilter過濾器的實(shí)現(xiàn)片段:

  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.     } 

這里有三個(gè)重要元素:

  • 過濾器的核心邏輯run函數(shù)實(shí)現(xiàn),其中調(diào)用了內(nèi)部函數(shù)buildCommandContext來構(gòu)建上下文內(nèi)容
  • 而buildCommandContext中調(diào)用了helper對(duì)象的buildZuulRequestHeaders方法來處理請(qǐng)求頭信息
  • helper對(duì)象是ProxyRequestHelper類的實(shí)例

接下來我們?cè)倏纯碢roxyRequestHelper的實(shí)現(xiàn):

  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.     } 

從上述源碼中,我們可以看到構(gòu)建頭信息的方法buildZuulRequestHeaders通過isIncludedHeader函數(shù)來判斷當(dāng)前請(qǐng)求的各個(gè)頭信息是否在忽略的頭信息清單中,如果是的話就不組織到此次轉(zhuǎn)發(fā)的請(qǐng)求中去。那么這些需要忽略的頭信息是在哪里初始化的呢?在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塊,通過調(diào)用ProxyRequestHelper的addIgnoredHeaders方法來添加需要忽略的信息到請(qǐng)求上下文中,供后續(xù)ROUTE階段的過濾器使用。這里的if/else塊分別用來處理全局設(shè)置的敏感頭信息和指定路由設(shè)置的敏感頭信息。而全局的敏感頭信息定義于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.     ... 

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

1. 全局設(shè)置:

  • zuul.sensitive-headers=

2. 指定路由設(shè)置:

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

二、重定向問題

在使用Spring Cloud Zuul對(duì)接Web網(wǎng)站的時(shí)候,處理完了會(huì)話控制問題之后。往往我們還會(huì)碰到如下圖所示的問題,我們?cè)跒g覽器中通過Zuul發(fā)起了登錄請(qǐng)求,該請(qǐng)求會(huì)被路由到某WebSite服務(wù),該服務(wù)在完成了登錄處理之后,會(huì)進(jìn)行重定向到某個(gè)主頁(yè)或歡迎頁(yè)面。此時(shí),仔細(xì)的開發(fā)者會(huì)發(fā)現(xiàn),在登錄完成之后,我們?yōu)g覽器中URL的HOST部分發(fā)生的改變,該地址變成了具體WebSite服務(wù)的地址了。這就是在這一節(jié),我們將分析和解決的重定向問題!

Spring Cloud Zuul對(duì)接Web網(wǎng)站

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

【本文為51CTO專欄作者“翟永超”的原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)通過51CTO聯(lián)系作者獲取授權(quán)】

 

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

責(zé)任編輯:趙寧寧 來源: 51CTO專欄
相關(guān)推薦

2017-05-19 15:13:05

過濾器Spring ClouZuul

2017-05-18 14:14:25

過濾器Spring ClouZuul

2017-07-31 15:47:50

Zuul統(tǒng)一處理

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協(xié)議

2017-05-04 22:30:17

Zuul過濾器微服務(wù)

2021-04-20 10:15:34

Spring ClouZuul架構(gòu)

2017-04-13 11:06:28

SpringCloud隨機(jī)端口

2009-06-25 14:54:22

Servlet轉(zhuǎn)發(fā)Servlet重定向

2024-12-20 07:30:00

重定向服務(wù)器端指令Next.js

2022-11-10 15:08:44

Linux輸入輸出

2010-08-17 11:35:00

2020-12-09 11:10:12

shellLinux管道

2009-06-30 15:37:27

Servlet和JSP
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)