cookie寫(xiě)入問(wèn)題

文章目錄

? ? 1 問(wèn)題分析

? ? 2 跟蹤C(jī)ookieUtils

? ? 3 解決host地址的變化

? ? 4 網(wǎng)關(guān)的反向代理

? ? 5 Host寫(xiě)入問(wèn)題

? ? ? ? 5.1 網(wǎng)關(guān)寫(xiě)入Host

? ? ? ? 5.2 敏感頭過(guò)濾導(dǎo)致cookie沒(méi)有寫(xiě)入

? ? ? ? 5.3 防止過(guò)濾器過(guò)濾Host

? ? 6 Zuul的敏感頭過(guò)濾

接上一篇鑒權(quán)微服務(wù)中間留下的問(wèn)題,專門(mén)來(lái)分析解決一下這個(gè)問(wèn)題,首先我們登錄,然后查看cookie:

在這里插入圖片描述

卻發(fā)現(xiàn)cookie中空空如也,這是為什么?

1 問(wèn)題分析

我們?cè)谥皽y(cè)試時(shí),清晰的看到了響應(yīng)頭中,有Set-Cookie屬性

在這里插入圖片描述

為什么在這里卻什么都沒(méi)有?

我們之前在講cors跨域時(shí),講到過(guò)跨域請(qǐng)求cookie生效的條件:

? ? 服務(wù)的響應(yīng)頭中需要攜帶Access-Control-Allow-Credentials并且為true。

? ? 響應(yīng)頭中的Access-Control-Allow-Origin一定不能為*,必須是指定的域名

? ? 瀏覽器發(fā)起ajax需要指定withCredentials 為true

看看我們的服務(wù)端cors配置:

在這里插入圖片描述

沒(méi)有任何問(wèn)題。

我們?cè)賮?lái)仔細(xì)看一下區(qū)別:調(diào)試的時(shí)候訪問(wèn)的是http://localhost:8087/login,但是瀏覽器訪問(wèn)的卻是http://api.leyou.com/api/auth/ogin,那我們?cè)儆眠@個(gè)地址調(diào)試一次:

在這里插入圖片描述

現(xiàn)在我們找到問(wèn)題了!——路徑問(wèn)題!

但是路徑變化會(huì)引起什么變化呢?——網(wǎng)關(guān)問(wèn)題或者nginx問(wèn)題二者都有可能產(chǎn)生問(wèn)題,要逐一排查

2 跟蹤C(jī)ookieUtils

除了上面那兩個(gè)原因,其次我們想,寫(xiě)cookie這個(gè)代碼有沒(méi)有問(wèn)題,為什么剛才有現(xiàn)在又沒(méi)有了呢?我們寫(xiě)cookie使用的是工具類:CookieUtils,先看一下可以正常生成的cookie信息:

返回header:

? ? LY_TOKEN=eyJhbGciOiJSUzI1NiJ9.eyJpZCI6MzIsInVzZXJuYW1lIjoiZGlhbmVtYXgiLCJleHAiOjE1NTUzMzE2MjF9.cYjoy_DaqlYx5GumxU7TExtENS1KBvNg_Sjdo1PBcW_tjYBu1xXtWfkwQV1_y03ttDcvs0PF3fQWkJOkmICv3n8Dy0do_M6KMMjG7fcNW-Mmk2blunOhw69o9ZSx0W0MSNGVMjR38OLyi9OumG3FzX2XjRB6GO_veBwMB5cmU; Domain=localhost; Path=/;HttpOnly

我們發(fā)現(xiàn)cookie的 domain屬性似乎不太對(duì)。我們?nèi)ebug跟蹤C(jī)ookieUtils,看看到底是怎么回事:

? ? 我們發(fā)現(xiàn)內(nèi)部有一個(gè)方法,用來(lái)獲取Domain,先通過(guò)request.getRequestURL()方法來(lái)獲取請(qǐng)求路徑

? ? 我們?cè)O(shè)置斷點(diǎn),在產(chǎn)生token的 cookieUtils中的build()函數(shù)設(shè)置斷點(diǎn),單步執(zhí)行

? ? 執(zhí)行到setDomain,首先由request.getRequestURL()獲取請(qǐng)求路徑

? ? 此時(shí)發(fā)現(xiàn)請(qǐng)求路徑被改變了,發(fā)現(xiàn)URL從http://www.leyou.com/變成了serverNamehttp://127.0.0.1:8087/login

? ? 之后經(jīng)過(guò)一些截取操作,serverName變成了0.0.1,

? ? 但如果是api.leyou.com的話,最終就變成了leyou.com,而leyou.com是所有相關(guān)網(wǎng)站的共同后綴,可以供leyou所有網(wǎng)站來(lái)訪問(wèn),這就很完美

在這里插入圖片描述

? ? 那原因是什么呢?——serverName的問(wèn)題

? ? serverName是http://127.0.0.1:8087/login,所以不管怎么截取都是有問(wèn)題的

? ? 問(wèn)題找到了:

? ? 我們請(qǐng)求時(shí)的serverName明明是:api.leyou.com,現(xiàn)在卻被變成了:127.0.0.1,因此計(jì)算domain是錯(cuò)誤的,cookie也是有domain(域) 的限制,一個(gè)網(wǎng)頁(yè),只能操作當(dāng)前域名下的cookie,但是現(xiàn)在我們看到的地址是0.0.1,而頁(yè)面是www.leyou.com,域名不匹配,cookie設(shè)置肯定失敗了!

3 解決host地址的變化

那么問(wèn)題來(lái)了:為什么我們這里的請(qǐng)求serverName變成了:127.0.0.1:8087呢?

這里的serverName其實(shí)就是請(qǐng)求的時(shí)的主機(jī)名:Host,serverName沒(méi)問(wèn)題,后續(xù)的自然會(huì)沒(méi)問(wèn)題,之所以改變,原因就是反向代理:當(dāng)訪問(wèn)leyou域名時(shí),這個(gè)域名指向了虛擬機(jī)

我們打開(kāi)nginx.conf,查看配置:

在這里插入圖片描述

要想解決這件事,首先要知道request.getRequestURL tomcat是怎么拿到域名地址的?

首先在瀏覽器F12控制臺(tái) 隨便打開(kāi)一個(gè)js請(qǐng)求

在這里插入圖片描述可以發(fā)現(xiàn)Request URL:http://www.leyou.com/plugins/jquery/jquery.min.js

上述URL在request中其實(shí)被分成了幾段來(lái)表示:

? ? Host:www.leyou.com——host

? ? GET /js/plugins/jquery/jquery.min.js HTTP/1.1——路徑和協(xié)議

全路徑其實(shí)就是請(qǐng)求 host+端口(默認(rèn)是80)+路徑 拼在一起得到的 ,影響我們得到域名的原因就是Host ,后面的路徑我們不關(guān)心! host其實(shí)是請(qǐng)求頭的一部分,當(dāng)我們反向代理的時(shí)候,nginx已經(jīng)將請(qǐng)求頭Host轉(zhuǎn)換成了192.168.124.1,于是在nginx反向代理時(shí)多設(shè)置一個(gè)Host頭。

將nginx的conf文件修改,添加:

proxy_set_header Host $host

? ? 1

$host代表的是上一次原生請(qǐng)求的host,原生的請(qǐng)求一定是api.leyou.com,它會(huì)讀取原生請(qǐng)求的host放到$host的位置,變成

proxy_set_header Host api.leyou.com

? ? 1

到此為止,重啟nginx

nginx -s reload

? ? 1

再次測(cè)試:

在這里插入圖片描述

還是有問(wèn)題。。。

4 網(wǎng)關(guān)的反向代理

其實(shí)剛才的問(wèn)題沒(méi)有找全,nginx把請(qǐng)求路徑代理到了htto://192.168.124.1:10010,但是我們拿到的serverName還是http://127.0.0.1:8087,怎么從10010端口變成了8087端口呢,因此這不光是nginx的問(wèn)題,網(wǎng)關(guān)也做了一次反向代理

因?yàn)榫W(wǎng)關(guān)是不能自己處理的,他會(huì)把請(qǐng)求轉(zhuǎn)發(fā)到微服務(wù)8087來(lái)進(jìn)行處理,現(xiàn)在我們把網(wǎng)關(guān)用debug啟動(dòng),在網(wǎng)關(guān)中有很多過(guò)濾器,這些過(guò)濾器默認(rèn)繼承自ZuulFilter,在其中一個(gè)PreDecorationFilter的run方法打個(gè)斷點(diǎn),查詢host,調(diào)用方法ctx.getRequest().getHeader("host"):

在這里插入圖片描述

發(fā)現(xiàn)此時(shí)的host是api.leyou.com 是正確的,說(shuō)明我們nginx的配置生效了,理論上此時(shí)放行,是不會(huì)出現(xiàn)錯(cuò)誤的,如果此時(shí)出現(xiàn)錯(cuò)誤,那就是網(wǎng)關(guān)沒(méi)有將host寫(xiě)進(jìn)去

5 Host寫(xiě)入問(wèn)題

5.1 網(wǎng)關(guān)寫(xiě)入Host

事實(shí)上,到此為止并沒(méi)有將host寫(xiě)進(jìn)去,原因是有個(gè)if判斷 ——porperties.isAddHostHeader(),成立才將host寫(xiě)入,點(diǎn)進(jìn)方法發(fā)現(xiàn)AddHostHeader是一個(gè)boolean值,值為false,屬于ZuulProperties,前綴是zuul,修改這個(gè)值很簡(jiǎn)單:

在這里插入圖片描述

繼續(xù)debug運(yùn)行看看有沒(méi)有寫(xiě)入成功:

在這里插入圖片描述

可以看到domain寫(xiě)入成功了,那我們來(lái)測(cè)試一下:

在這里插入圖片描述

發(fā)現(xiàn),響應(yīng)頭中還是沒(méi)有set-cookie!事實(shí)上到這里還沒(méi)有結(jié)束,單單設(shè)置這個(gè)是不行的

5.2 敏感頭過(guò)濾導(dǎo)致cookie沒(méi)有寫(xiě)入

過(guò)濾器中還有一個(gè)addIgnoredHeaders方法,會(huì)對(duì)一些頭進(jìn)行忽略,會(huì)對(duì)敏感頭進(jìn)行過(guò)濾

在這里插入圖片描述

會(huì)發(fā)現(xiàn),這里會(huì)通過(guò)一個(gè)屬性為SensitiveHeaders的屬性,來(lái)獲取敏感頭列表,然后添加到IgnoredHeaders中,這些頭信息就會(huì)被忽略。

而這個(gè)SensitiveHeaders的默認(rèn)值就包含了set-cookie:

在這里插入圖片描述

現(xiàn)在set-cookie被濾掉,因此問(wèn)題和原因我們知道了,但是先不管,我們先來(lái)看Host可不可以正常傳遞,debug發(fā)現(xiàn)Host還是沒(méi)有被拿到?。?!

5.3 防止過(guò)濾器過(guò)濾Host

ZuulFilter下面還有一個(gè)叫RibbonRoutingFilter的過(guò)濾器,做負(fù)載均衡路由的方法

在這里插入圖片描述

它有一個(gè)構(gòu)建上下文的方法:

在這里插入圖片描述

在構(gòu)建上下文中會(huì)先獲取頭信息:

在這里插入圖片描述

然后對(duì)頭做一些判斷:

在這里插入圖片描述

判斷方法:

在這里插入圖片描述

如果是被允許的頭信息,才會(huì)將其添加到Headers中去,如果頭是被忽略的,則不會(huì)被添加,但是下面有一個(gè)switch語(yǔ)句,如果name是host,則忽略!因此host永遠(yuǎn)不會(huì)被添加進(jìn)去

最后:盡管yml中設(shè)置了true,Host被添加進(jìn)去了,但是由于這個(gè)過(guò)濾器,又被忽略掉了。因此無(wú)論如何我們都沒(méi)辦法把Host添加進(jìn)去,這是一個(gè)bug

解決辦法:

對(duì)比了上一個(gè)SpringCloud版本的源碼,發(fā)現(xiàn)是沒(méi)有if判斷的,說(shuō)明是因?yàn)榧恿诉@一段導(dǎo)致錯(cuò)誤,因此我們修改一下版本

在這里插入圖片描述

再次測(cè)試:

在這里插入圖片描述

Host終于被添加進(jìn)來(lái)了!此時(shí)再次debug程序,可以看到已經(jīng)拿到了正確的domain:

在這里插入圖片描述

6 Zuul的敏感頭過(guò)濾

我們已經(jīng)在前面5.2部分分析了cookie沒(méi)有被寫(xiě)入的原因,我們現(xiàn)在來(lái)解決它:

解決方案有兩種:

全局設(shè)置:

? ? zuul.sensitive-headers=

? ? 在這里插入圖片描述

指定路由設(shè)置:

? ? zuul.routes.<routeName>.sensitive-headers=

? ? zuul.routes.<routeName>.custom-sensitive-headers=true

思路都是把敏感頭設(shè)置為null

現(xiàn)在再來(lái)測(cè)試一次:

在這里插入圖片描述

一切正常,到此位置,cookie的寫(xiě)入問(wèn)題被完美解決了

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • API定義規(guī)范 本規(guī)范設(shè)計(jì)基于如下使用場(chǎng)景: 請(qǐng)求頻率不是非常高:如果產(chǎn)品的使用周期內(nèi)請(qǐng)求頻率非常高,建議使用雙通...
    有涯逐無(wú)涯閱讀 2,927評(píng)論 0 6
  • 深入淺出HTTP協(xié)議(WEB開(kāi)發(fā)和面試必備) 1.基礎(chǔ)概念篇 a.簡(jiǎn)介 HTTP是Hyper Text Trans...
    半世韶華憶闌珊閱讀 1,341評(píng)論 0 7
  • 國(guó)慶假期的最后一天,回顧這周,爬了山,看了電影,讀了書(shū),寫(xiě)了文章,投了稿,做了飯,慶了生,也算是充實(shí)。當(dāng)然,這之后...
    聶一一閱讀 129評(píng)論 0 0
  • 三、風(fēng)雨進(jìn)村路 成都,都說(shuō)是一座來(lái)了就不想走的城市。誠(chéng)然,對(duì)這座城市,已經(jīng)流連無(wú)數(shù)次了,不論是自駕川西、還是西藏返...
    xxq相伴閱讀 448評(píng)論 1 4
  • 今天是周一,坐在課堂上的我由于嚴(yán)重缺乏睡眠,老師講的課我是豎起了耳朵也沒(méi)聽(tīng)懂。于是,聊聊這個(gè)周末去首爾的feeli...
    最美四月天77閱讀 328評(píng)論 0 0

友情鏈接更多精彩內(nèi)容