1. 程式人生 > 實用技巧 >nginx 反向代理session失效問題

nginx 反向代理session失效問題

背景

經瞭解,他對同一個專案使用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中,如圖

因此在下次請求伺服器時,瀏覽器無法設定requestCookieheader的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,問題解決。

轉發自:https://www.cnblogs.com/spec-dog/p/13292111.html