Java解決cookie寫入問題
當我們使用
CookieUtils.setCookie(request, response, this.prop.getCookieName(), token, this.prop.getExpire() * 60);
將token設定進入cookie時,頁面重新整理並不能獲取到cookie值,這是為什麼呢?
問題分析
我們在之前測試時,清晰的看到了響應頭中,有Set-Cookie屬性,為什麼在這裡卻什麼都沒有?
我們之前在講cors跨域時,講到過跨域請求cookie生效的條件:
-
服務的響應頭中需要攜帶Access-Control-Allow-Credentials並且為true。
-
響應頭中的Access-Control-Allow-Origin一定不能為*,必須是指定的域名
-
瀏覽器發起ajax需要指定withCredentials 為true
看看我們的服務端cors配置:
沒有任何問題。
再看客戶端瀏覽器的ajax配置,我們在js/common.js
中對axios進行了統一配置:
一切OK。
那說明,問題一定出在響應的set-cookie頭中。我們再次仔細看看剛才的響應頭:
我們發現cookie的domain屬性似乎不太對。
cookie也是有域的限制,一個網頁,只能操作當前域名下的cookie,但是現在我們看到的地址是0.0.1,而頁面是www.xx.com域名不匹配,cookie設定肯定失敗了!
跟蹤CookieUtils
我們去Debug跟蹤CookieUtils,看看到底是怎麼回事:
我們發現內部有一個方法,用來獲取Domain:
它獲取domain是通過伺服器的host來計算的,然而我們的地址竟然是:127.0.0.1:8087,因此後續的運算,最終得到的domain就變成了:
問題找到了:我們請求時的serverName明明是:api.xx.com,現在卻被變成了:127.0.0.1,因此計算domain是錯誤的,從而導致cookie設定失敗!
解決方法:
1、替換spring的jdk
Finchley.SR1版本會存在獲取不到cookie值的bug,所以要spring-cloud-dependencies替換成Finchley.RELEASE
2、解決host地址的變化
這裡的server name其實就是請求的時的主機名:Host,之所以改變,有兩個原因:
-
我們使用了nginx反向代理,當監聽到api.leyou.com的時候,會自動將請求轉發至127.0.0.1:10010,即Zuul。
-
而後請求到達我們的閘道器Zuul,Zuul就會根據路徑匹配,我們的請求是/api/auth,根據規則被轉發到了 127.0.0.1:8087 ,即我們的授權中心。
我們首先去更改nginx配置,讓它不要修改我們的host:proxy_set_header Host $host;
把nginx進行reload: nginx -s reload
這樣就解決了nginx這裡的問題。但是Zuul還會有一次轉發,所以要去修改閘道器的配置(xxx-gateway工程):
重啟後,我們再次測試。
最後計算得到的domain:
3、Zuul的敏感頭過濾
Zuul內部有預設的過濾器,會對請求和響應頭資訊進行重組,過濾掉敏感的頭資訊:
會發現,這裡會通過一個屬性為SensitiveHeaders
的屬性,來獲取敏感頭列表,然後新增到IgnoredHeaders
中,這些頭資訊就會被忽略。
而這個SensitiveHeaders
的預設值就包含了set-cookie
:
全域性設定:
zuul.sensitive-headers=
思路都是把敏感頭設定為null
最後的測試