原來直接用request.getRemoteAddr();擷取ip,可以到真實的ip,但是修改成mod_proxy方式後,request.getRemoteAddr();是發起求apache伺服器的ip,大多數情況是本機。
所以應該修改為:
String ip = request.getHeader("x-forwarded-for");
if (ip != null && !"unknown".equalsIgnoreCase(ip)) {
String[] ipList = ip.split(",");
for (String ipItem : ipList) {
//ip min length 7: 0.0.0.0
if (ipItem.length() >= 7 && !"unknown".equalsIgnoreCase(ipItem)) {
return ipItem;
}
}
}
return null;//一定是配置有問題了。
至於網上流傳的Proxy-Client-IP,還有八輩子用不到的WEBLogic自訂頭WL-Proxy-Client-IP等等都是浮動,半點鐘不可靠,請求端可以在頭域中任意添加。
而只有這個XFF是apache擷取到客端ip然後轉寄給後端,這兩端的轉寄對我們而言是真實可信的。如果你啟動了mod_proxy,那麼在後端的
web容器中擷取XFF就一定是在apache中看到的ip(指串連到apache的用戶端,它有可能本身就是代理,但這稱們平時直接getRemoteAddr()是
一致的),對於apache反向 Proxy而言,它一定不會是unknown,上面的unknown是為了相容squid的 forwarded_for off情境。如果這樣取不到,那麼根本沒有
必要再取getRemoteAddr()還不如直接return null或return "127.0.0.1".
千萬要注意的是,按IETF的XFF規範,對於原來的XFF應該保留,代理把當前擷取的IP附加到最後面。如果我們取XFF的第一個非unknown就有可能是用戶端
提交的值,從而被客端欺騙了,所以應該在apache中把原來的值給unset掉:
RequestHeader unset x-forwarded-for
這樣apache會把原來的x-forwarded-for清這,然後把當前用戶端的值作為x-forwarded-for轉寄給後端。