歡迎您光臨本站 註冊首頁

nginx反向代理導致session失效的問題解決

←手機掃碼閱讀     madbeef @ 2020-06-05 , reply:0

一同事求援:後臺系統的登錄成功了,但不能成功登進系統,仍然跳轉到登錄頁,但同一套代碼另一個環境卻沒有問題。

背景

經瞭解,他對同一個項目使用tomcat部署了兩個環境,一個在開發服務器上,一個在他本機,兩個環境代碼配置完全相同。兩邊通過同一個nginx進行反向代理,nginx配置大致如下,

 location /health/ { proxy_pass http://192.168.40.159:8081/health/; #無問題的配置 } location /health-dev/ { proxy_pass http://192.168.40.202:8080/health/; #有問題的配置 }


一個反向代理到開發環境,一個反向代理到本機服務。

定位

既然代碼配置完全相同,那麼問題很大可能就出現在nginx的反向代理上。

因為兩邊location路徑不同(即瀏覽器路徑不同),但是反向代理的服務端路徑卻相同,結合session的基本原理,如下圖,

  1. 當瀏覽器第一次打開頁面時,服務端會為這次會話創建一個session,並將session id通過response的header傳遞給瀏覽器,header一般為 Set-COOKIE: JSESSIOnID=xxxxx; Path=xxxx

  2. 瀏覽器接收到響應後,如果header Set-COOKIE 中path的值與瀏覽器地址路徑匹配,則將該header值存於瀏覽器的COOKIE中

  3. 瀏覽器在下次請求服務器時,將COOKIE中的JSESSIONID值通過request的header上報給服務端,header一般為 COOKIE: JSESSIOnID=xxxx;

  4. 服務端可通過該JSESSIONID來定位到對應的session

nginx反向代理按這種方式配置時

 location /health-dev/ { proxy_pass http://192.168.40.202:8080/health/; }


瀏覽器訪問 http://www.domian.com/health-dev 時,服務端返回的 Set-COOKIE 的 Path 值為 /health (因為中間有反向代理,服務端並不知道代理前的路徑是啥,是按最終請求服務端的路徑設置),如圖

因為瀏覽器訪問地址的路徑 /health-devSet-COOKIE 的 Path /health 不匹配,所以瀏覽器並不會將其值存入COOKIE中,如圖

因此在下次請求服務器時,瀏覽器無法設置request COOKIE header的 JSESSIONID 值,服務器無法定位到對應的session,因此會將其當做第一次請求,創建一個新的session,如此反覆,因此就算你登錄認證通過了,但服務器返回的登錄憑證(JSESSIONID)瀏覽器不會保存,並在下次請求時攜帶,導致服務器認為你是一個新的請求,當然就會又跳到登錄頁面了。

解決

nginx有一個命令 proxy_COOKIE_path (參考: proxy_COOKIE_path)可將服務器返回的 Set-COOKIE 中的path進行修改,格式為 proxy_COOKIE_path 原路徑 目標路徑 ,我們在配置中添加 proxy_COOKIE_path 如下。

 location /health-dev/ { proxy_pass http://192.168.40.202:8080/health/; proxy_COOKIE_path /health /health-dev; }


重啟nginx,問題解決。


[madbeef ] nginx反向代理導致session失效的問題解決已經有146次圍觀

http://coctec.com/docs/nginx/show-post-237105.html