記一次nginx反向代理引發的沒法登陸問題

背景

事情是這樣的,公司之前開發了一套系統,可是由於國家政策緣由下線了,時隔兩年,如今能夠從新上線了,可是隻有代碼,相關環境的配置是沒有的。在從新上線的過程當中,遇到了系統沒法登錄的問題。這套系統架構是這樣的:nginx做爲web接入層,數據處理會反向代理到tomcat上跑的java服務。一開始我懷疑是否是代碼邏輯有問題,可是開發稱代碼是沒問題的,爲此,開發還將獲取數據請求跳過nginx直接拋給Tomcat,結果就真的沒問題了。可是實際生產中是不能這樣跑的,由於這樣會暴露處理數據的Tomcat。因此只能在nginx這裏找問題。html

排查過程

現象是這樣的,登陸的時候會成功進入系統,可是會馬上跳回登陸頁面。登陸的過程會有一條post請求將登陸信息上傳給系統,還有一條get請求獲取登陸狀態,可是我不清楚獲取登陸狀態的邏輯是怎樣的,判斷條件是什麼,本想讓開發看一下 代碼邏輯的,可是開發也看不出個因此然來。接着我看了post和get請求的包頭信息,包頭信息以下:
post請求包頭信息
image.png
get請求頭區別
image.png
然而僅僅看這兩個包頭信息我看不出什麼異常,因此我讓開發將代碼改成直接跳過nginx能夠登陸的狀況,我想對比能登陸和不能登陸的狀況下有什麼區別,如下是能登陸的狀況下的包頭信息:
post請求包頭信息
image.png
get請求頭區別
image.png
對比了兩種狀況的包頭信息,我發現了一個區別(ps:請忽略Access-Control相關頭信息差別,這是後面解決跨域加的),那就是不能登陸的時候post和get請求都有set-cookie,而能夠登陸的時候,只有post請求有set-cookie。因此我猜測是post請求的時候登陸成功會生成一個cookie,而後get請求去讀取cookie,獲取到cookie即爲登陸狀態。因此我又對比了兩種狀況的cookie。不過在看cookie的具體狀況以前,我要先說清楚兩種狀況下請求的區別。不能登陸的狀況下,使用了nginx作反向代理,http://域名/字符串/XXX 會被反向代理到 http://域名:端口/項目名/XXX 即用項目名替代固定的字符串(聽說這樣作是爲了區分測試環境和生產環境的),而後能夠登陸的狀況是不通過nginx代理,直接請求了http://域名:端口/項目名/XXX 。由於cookie裏面涉及到這些,因此要先說清楚。下面是cookie的具體信息
不能登陸狀況下post請求的cookie信息
1.jpg
不能登陸狀況下get請求的cookie信息
2.jpg
能夠登陸狀況下post請求的cookie信息
image.png
能夠登陸狀況下get請求的cookie信息
4.jpg
能夠看到的出來,能夠登陸的狀況下,確實是get請求去請求了post請求響應的cookie。那麼爲何通過nginx以後,get請求就沒有這樣去獲取post響應的cookie呢?我查找‘nginx cookie’關鍵詞,看到《解決nginx proxy_pass反向代理cookie,session丟失的問題》,瞭解到cookie_path要匹配請求的url才能獲取到cookie,因而不能登陸問題就能獲得合理的解釋:當post請求http://域名/字符串/XXX 時,通過nginx反向代理到http://域名:端口/項目名/XXX ,此時cookie_path是在項目名下(從post請求包頭能夠看到),而後get請求http://域名/字符串/YYY ,可是這條請求裏面沒有項目名,獲取不到上面post請求響應的放在項目名目錄下面的cookie,因此被判斷爲沒有登陸的狀態,返回了登陸頁,同時get請求也生成了一個cookie放在了項目名目錄下。java

問題解決

第一種方案:修改cookie_path,nginx裏面提供了proxy_cookie_path指令修改cookie_path,用法:proxy_cookie_path 原地址 修改地址 官網傳送門
通過測試,修改地址只要知足請求url域名後的目錄最左匹配規則都是能夠的,好比個人請求是http://域名/a/b/c/d/xxx ,反向代理到http://域名:端口/E/b/c/d/xxx ,那麼cookie_path修改地址能夠設置爲/,/a,/a/b,/a/b/c,/a/b/c/d,示例:nginx

location /a/ {
    proxy_pass   http://127.0.0.1:8080/E/;
    proxy_cookie_path  /E /a;
}

第二種方案:修改請求地址,讓請求地址和反向代理地址相匹配,如請求地址http://域名/字符串/XXX 被反向代理到 http://域名:端口/項目名/XXX ,那麼能夠修改請求地址爲http://域名/項目名/XXX ,這樣就不須要配置proxy_cookie_path。web

參考:
解決nginx proxy_pass反向代理cookie,session丟失的問題跨域

相關文章
相關標籤/搜索