<b># 前情提要</b>
将cas部署到阿裡雲,使用slb進行前端負載以及ssl,後端使用tomcat作為應用伺服器。
按照正常方式部署上去之後,遇到如下問題:
1. ssl下使用redirect,自動跳轉到80端口。
2. cas無法擷取到用戶端的ip,cookies校驗出錯,導緻單點登入功能失效。
<b># 查找原因</b>
1. tomcat預設情況下的redirect會是80
2. cas的cookies檢查以及寫入程式使用request.getremoteaddr()擷取到的都是slb的ip,并非實際用戶端的ip,而且slb的ip不固定(貌似阿裡的slb是一個n多台機器的玩意,每次一個頁面請求過來,每個資源的請求ip都不同),我使用的杭州的slb,ip段在100.97.*.*這個範圍。
<b># 解決問題</b>
1. 設定tomcat的使用前端代理模式,解決tomcat中程式的redirect沒有跳轉到ssl的問題。
在server.xml中找到對外開放的connector,我的是用的nio-8080
<connector port="8080"
proxyname="這裡是域名"
proxyport="443"
scheme="https"
secure="true"
protocol="org.apache.coyote.http11.http11nioprotocol"
connectiontimeout="20000" uriencoding="utf-8" usebodyencodingforuri="true"
redirectport="8443" />
上述的含義是,
slb的域名是proxyname
slb對外端口是proxyport
slb使用的協定是https
slb是否開啟ssl:secure
2. 設定x-forwarded過濾器
在server.xml中的<engine>元素下增加如下内容:
<valve classname="org.apache.catalina.valves.remoteipvalve"
internalproxies="100\.97\.\d{1,3}\.\d{1,3}" />
internalproxies的意思是:tomcat僅接受這個ip段過來的請求中的x-forwarded系列的值覆寫為remote_addr等。加了這個過濾器之後使用request.getremoteaddr()就可以擷取到正确的用戶端ip了。需要注意的是,這個ip段需要根據你所用的slb來寫。
在tomcat裡,internalproxies的預設值為(無法覆寫到slb的ip段):
10\.\d{1,3}\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3}|169\.254\.\d{1,3}\.\d{1,3}|127\.\d{1,3}\.\d{1,3}\.\d{1,3}|172\.1[6-9]{1}\.\d{1,3}\.\d{1,3}|172\.2[0-9]{1}\.\d{1,3}\.\d{1,3}|172\.3[0-1]{1}\.\d{1,3}\.\d{1,3}
<b>特别注意:</b>
<b>這個<value>一定要寫在<engine>元素下!</b>
我查了很多網上的資料,都是說在server.xml裡面加上這個<value>,于是我看到tomcat有預設定義一個<value>在<host>裡面,于是我也跟着寫裡面,但是就是不生效。然後我特姆調試了兩天,結果一直不生效,最後在tomcat文檔裡找到這麼一句話:
this valve may be used at the <code>engine</code>, <code>host</code> or <code>context</code> level as required. normally, this valve would be used at the <code>engine</code> level.
其他參數請參考tomcat的文檔:
https://tomcat.apache.org/tomcat-8.0-doc/config/valve.html#remote_address_filter
希望此篇能給有需要的人帶來幫助。