在Linux環境下,利用了Nginx的強勢—反向 Proxy,結果導致用request.getRemoteAddr()擷取的IP均為公司的Proxy 伺服器的IP,日誌記錄嚴重不準確!
大家都知道在伺服器端擷取用戶端的IP地址的方法是:request.getRemoteAddr(),這種方法在大部分情況下都是有效。
但是在通過了Nginx,Squid等反向 Proxy軟體就不能擷取到用戶端的真實IP地址了。
如果使用了反向 Proxy軟體,例如將http://192.168.101.88:80/的URL反向 Proxy為http://pay.kedou.com/的URL時,用request.getRemoteAddr()方法擷取的IP地址是:127.0.0.1 或 192.168.101.88,而並不是用戶端的真實IP。
原來是client端直接請求服務端,走A路線請求,這時候通過request.getRemoteAddr()方法可以準備的擷取用戶端的IP。但是做了代理之後呢,client端不是直接請求服務端,而是走B線路請求Proxy 伺服器,由代理器去請求服務端,這時候服務端通過request.getRemoteAddr()方法拿到的理所當然是
Proxy 伺服器的地址了。
經過代理以後,由於在用戶端和服務之間增加了中介層,因此伺服器無法直接拿到用戶端的IP,伺服器端應用也無法直接通過轉寄請求的地址返回給用戶端。但是在轉寄請求的HTTP頭資訊中,增加了X-FORWARDED-FOR資訊。用以跟蹤原有的用戶端IP地址和原來用戶端請求的伺服器位址。當我們訪問 http://pay.kedou.comindex.htm/時,其實並不是我們瀏覽器真正訪問到了伺服器上的index.htm/ 檔案,而是先由Proxy 伺服器去訪問http://192.168.101.88:80/index.htm,Proxy 伺服器再將訪問到的結果返回給我們的瀏覽器,因為是Proxy 伺服器去訪問index.htm 的,所以index.htm 中通過request.getRemoteAddr()的方法擷取的IP實際上是Proxy 伺服器的地址,並不是用戶端的IP地址。
於是可得出獲得用戶端真實IP地址的
方法一: public String getRemortIP(HttpServletRequest request){if(request.getHeader(” x-forwarded-for ” ) == null){return request.getRemoteAddr(); }return request.getHeader(” x-forwarded -for”); 可是當我訪問http://pay.kedou.comindex.htm/時,返回的IP地址始終是unknown,也並不是如上所示的127.0.0.1 或 192.168.101.88了於是可得出獲得用戶端真實IP地址的
方法二: public String getIpAddr(HttpServletRequest request){ String ip = request.getHeader(” x-forwarded-for ” ); if(ip == null || ip.length() == 0|| ”unknown” .equalsIgnoreCase(ip)){ ip = request.getHeader(” Proxy-Client-IP” ); }if(ip == null || ip.length() == 0|| ”unknown” .equalsIgnoreCase(ip)){ ip = request.getHeader(” WL-Proxy-Client-IP” ); }if(ip == null || ip.length() == 0|| ”unknown” .equalsIgnoreCase(ip)){ ip = request.getRemoteAddr(); }return ip; }
可是,如果通過了多級反向 Proxy的話,X-Forwarded-For的值並不止一個,而是一串Ip值,究竟哪個才是真正的使用者端的真實IP呢?
答案是取X-Forwarded-For中第一個非unknown的有效IP字串。
如:
X-Forwarded-For:192.168.101.88, 192.168.101.128, 192.168.101.126
使用者真實IP為:192.168.101.88 於是擷取最終版代碼 // 擷取用戶端IP地址,支援Proxy 伺服器 publicstatic String getIpAddress(HttpServletRequest request){ String ip = request.getHeader("x-forwarded-for"); String localIP = "127.0.0.1"; if((ip == null)||(ip.length() == 0)||(ip.equalsIgnoreCase(localIP))||"unknown".equalsIgnoreCase(ip)){ ip = request.getHeader("Proxy-Client-IP"); }if((ip == null)||(ip.length() == 0)||(ip.equalsIgnoreCase(localIP))||"unknown".equalsIgnoreCase(ip)){ ip = request.getHeader("WL-Proxy-Client-IP"); }if((ip == null)||(ip.length() == 0)||(ip.equalsIgnoreCase(localIP))||"unknown".equalsIgnoreCase(ip)){ ip = request.getRemoteAddr(); }return ip; }