1. 程式人生 > >request.getRemoteAddr()怎麼獲取使用者真實的IP地址

request.getRemoteAddr()怎麼獲取使用者真實的IP地址

request.getRemoteAddr()如何獲取使用者真實的IP地址
  要獲得使用者真實的IP地址需要藉助請求報頭中的x-forwarded-for變數。
request.getHeader("x-forwarded-for");


完整例項如下

<%@ page contentType="text/html; charset=gb2312" %>
<%@ page import="java.util.*"%>
<%
String realIP = request.getHeader("x-forwarded-for");
String ip = request.getRemoteAddr();
Enumeration enum = request.getHeaderNames();
while(enum.hasMoreElements())
{
  String name = (String)enum.nextElement();
  String value = request.getHeader(name);
  out.write(name + "=" + value + "<br$amp;>quot;$);
}
%>
你的IP地址是:<%=realIP%>


在很多應用下都可能有需要將使用者的真實IP記錄下來,這時就要獲得使用者的真實IP地址,在JSP裡,獲取客戶端的IP地址的方法是:request.getRemoteAddr(),這種方法在大部分情況下都是有效的。但是在通過了Apache,Squid等反向代理軟體就不能獲取到客戶端的真實IP地址了。

  這段時間在做IP統計的程式設計,由於伺服器作了叢集,使用了反向代理軟體,將[1]的URL反向代理為[2]的URL時,用request.getRemoteAddr()方法獲取的IP地址是:127.0.0.1 或 192.168.1.110,而並不是客戶端的真實IP。這是什麼原因呢?

   這是反向代理的原因。經過代理以後,由於在客戶端和服務之間增加了中間層,因此伺服器無法直接拿到客戶端的IP,伺服器端應用也無法直接通過轉發請求的 地址返回給客戶端。但是在轉發請求的HTTP頭資訊中,增加了X-FORWARDED-FOR資訊。用以跟蹤原有的客戶端IP地址和原來客戶端請求的服務 器地址。當我們訪問/ [3]時,其實並不是我們瀏覽器真正訪問到了伺服器上的index.jsp檔案,而是先由代理伺服器去訪問 [4],代理伺服器再將訪問到的結果返回給我們的瀏覽器,因為是代理伺服器去訪問index.jsp的,所以index.jsp中通過request.getRemoteAddr()的方法獲取的IP實際上是代理伺服器的地址,並不是客戶端的IP地址。
於是可得出獲得客戶端真實IP地址的方法一:
public String getIpAddr(HttpServletRequest request) {
2    String ip = request.getHeader("x-forwarded-for");
3   if(ip == null || ip.length() == 0) {
4       ip = request.getRemoteAddr();
5     }
6    return ip;
7   }

可是當我訪問/ [5]時,返回的IP地址始終是unknown,也並不是如上所示的127.0.0.1 或 192.168.1.110了,而我訪問 [6]時,則能返回客戶端的真實IP地址,寫了個方法去驗證。
1<%@ page import="java.util.*" %>
2<table border=1 cellspacing=0 cellpadding=0 align=center>
3<tr>
4<th>Name</th>
5<th>Value</th>
6</tr>
7<%
8Enumeration enumNames;
9String strName,strValue;
10
11enumNames = request.getHeaderNames();
12while(enumNames.hasMoreElements()){
13   strName = (String)enumNames.nextElement();
14   strValue = request.getHeader(strName);
15  %>
16  <tr>
17  <td$amp;>amp;$lt;%=strName%$amp;>amp;$lt;/td>
18  <td$amp;>amp;$lt;%=strValue%$amp;>amp;$lt;/td>
19  </tr>
20  <%
21}
22%>
23<tr>
24</table>
出來的結果:X-Forwarded-For: unknown 。X-Forwarded-For確實存在,但其值卻為unknown,繼續找原因。上網搜了搜,原因出在了Squid上。

squid.conf 的配製檔案 forwarded_for 項預設是為on,如果 forwarded_for 設成了 off  則:

X-Forwarded-For: unknown

一查,發現forwarded_for 項設為了off,原因找到了,把forwarded_for 項設為了on,重啟後,訪問/ [7] 獲得的IP是客戶端的真實IP。

  於是可得出獲得客戶端真實IP地址的方法二:
1  public String getIpAddr(HttpServletRequest request) {
2     String ip = request.getHeader("x-forwarded-for");
3    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
4       ip = request.getHeader("Proxy-Client-IP");
5     }
6    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
7       ip = request.getHeader("WL-Proxy-Client-IP");
8     }
9    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
10       ip = request.getRemoteAddr();
11     }
12    return ip;
13   }
可是,如果通過了多級反向代理的話,X-Forwarded-For的值並不止一個,而是一串Ip值,究竟哪個才是真正的使用者端的真實IP呢?

  答案是取X-Forwarded-For中第一個非unknown的有效IP字串。

  如:
  X-Forwarded-For:192.168.1.110, 192.168.1.120, 192.168.1.130, 192.168.1.100
  使用者真實IP為: 192.168.1.110