nginx反向代理cas應用實踐(多地址跳轉)
(ps:本文僅針對對nginx反向代理有一定了解的朋友,如不了解請自行百度)
問題出現在這個網站應用上,他們使用了cas架構,在系統登錄的url地址和應用的地址不在一起:如下
當使用系統的地址訪問時,他跳轉到下面的位置,顯示了登錄頁面:
當登錄系統後,又跳轉回192.168.20.150這個地址上。
查了一下cas,應該是用於登錄權限管理的。
通過fiddle跟蹤,發現在使用http://192.168.20.164登錄時,返回了如下信息
紅線標出了,瀏覽器下次跳轉的url,繼續跳轉,返回:
繼續跳,返回:
到這裏,再跳轉到index.aspx就進入系統了。
是不是有點暈!總結一下:
進入系統,一共進行了三次跳轉,系統的登錄首頁在192.168.20.164上面,點擊登錄成功後,就跳轉到192.168.20.150上面去。
可以看出192.168.20.164是一個管理登錄的服務器,系統的真實服務器在192.168.20.150上面。
好了,大體情況清楚了,但問題是如何實現我們的需求呢??
1、通過網絡方式,開通兩邊的網絡,這樣肯定應該是可以,但太暴力了,也不允許,不現實,pass掉。
2、在中間服務器,使用nginx反向代理,但常規的方式,顯然滿足不了當前的情況,如果瀏覽器根據響應返回的location跳轉,就會訪問不到了,只能看如何在響應頭返回前端瀏覽器前,更改掉Location,讓它繼續指向我們自己的nginx服務器地址。
所以,我安裝一個臺新的centos服務器在192.168.253.155上面,安裝nginx 1.9.9,因為需要改變響應頭中的Location值,需額外安裝ngx_headers_more模塊。
在《nginx替換響應頭(重點:如何在替換時加上if判斷)》這篇文章中有詳細的介紹。
nginx.conf主要配置如下:
map $upstream_http_Location $location{ ~http://192.168.20.150/(?<param>.*) $param; default $upstream_http_Location; } ... ... server { listen 80; server_name localhost; location /xt/ { set $qz http://192.168.253.155/; more_set_headers -s '302' 'Location:$qz$location'; add_header Cache-Control 'no-cache'; add_header Cache-Control 'no-store'; sub_filter '/smportal-cas/' '/xt/smportal-cas/'; sub_filter_once off; proxy_pass http://192.168.20.164:XXXX/; } location / { ... ... proxy_pass http://192.168.20.150/; } ... ...
最上面的map用於將登錄頁面返回響應頭中Location為的內容映射到變量$location中去,我們可以看到,在192.168.20.164上登錄成功後,首先就跳轉到http://192.168.20.150/xxx/xxx.aspx?ticket=xxxxxx,如下圖:
這時我們通~http://192.168.20.150/(?<param>.*) $param;取出150/後面的內容(因為每次後面的內容會不同)賦到$location中。
(註:(?<xxx> xxxx)是nginx中通過正則取值到變量的方法,此處首先賦值給了$param,然後通過map映射到$location。
至於為什麽不用$upstream_http_Location直接取值,用if判斷呢?前面推薦的那篇文章寫的很清楚。)
接下來配置,將http://192.168.253.155/xt/的訪問代理到http://192.168.20.164上面,讓用戶可以訪問登錄頁面。
其中
set $qz http://192.168.253.155/; #設置變量$qz為我們自己的地址
more_set_headers -s '302' 'Location:$qz$location'; #將$qz和$location(保存著剛才取到需跳轉url的後面路徑和參數部分)拼接成指向我們自己nginx的地址,即替換原先url中http://192.168.20.150為http://192.168.253.155
最後配置http://192.168.253.155/的訪問代理到http://192.168.20.150上面去,即完成了本次的任務。
(ps: sub_filter的部分,是因為在登錄頁面中有很js,包括登錄按鈕提交時的url都使用了絕對的地址,所以需要在返回頁面到前端前替換掉這些url,增加我們前輟/xt/,這樣訪問才沒有問題。
其實,實際情況中, 有很多的限制,比如單位b訪問我單位的nginx服務器時,由於中間有網絡設備不好調整,限制訪問端口只能用80,而不能增加其它端口,所以配置只能使用子路徑來區分多代理,本來可以用多端口就不用sub_filter替換內容了。
在實驗的過程中,也嘗試過用\代理登錄的192.168.20.164服務器,用子路徑\xt代理系統服務器,最後引出了cookie的設置問題,雖最終沒這樣設,但發現nginx可以設置cookie的path,以保證代理時路徑改變,cookie作對應的調整,特在此備註一下:
proxy_cookie_path / /xt/;#將cookie的path的/映射為 /xt/
感覺nginx真的很方便,原先為了實現反向代理、跨域,可是用編程實現的,唉。
)
nginx反向代理cas應用實踐(多地址跳轉)