`
suoyihen
  • 浏览: 1361162 次
文章分类
社区版块
存档分类
最新评论

开发网页游戏过程记录12-获取玩家的真实ip地址

 
阅读更多

在很多应用下都可能有需要将用户的真实IP记录下来,这时就要获得用户的真实IP地址,在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的。但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实IP地址了。

可是当服务器作了集群,使用了反向代理软件,将http://192.168.1.110:2046/的URL反向代理为http://www.xxx.com/的URL时,用request.getRemoteAddr()方法获取的IP地址是:127.0.0.1 或 192.168.1.110,而并不是客户端的真实IP。这是什么原因呢?
这是反向代理的原因。经过代理以后,由于在客户端和服务之间增加了中间层,因此服务器无法直接拿到客户端的IP,服务器端应用也无法直接通过转发请求的地址返回给客户端。但是在转发请求的HTTP头信息中,增加了X-FORWARDED-FOR信息。用以跟踪原有的客户端IP地址和原来客户端请求的服务器地址。当我们访问http://www.xxx.com/index.jsp/时,其实并不是我们浏览器真正访问到了服务器上的index.jsp文件,而是先由代理服务器去访问http://192.168.1.110:2046/index.jsp,代理服务器再将访问到的结果返回给我们的浏览器,因为是代理服务器去访问index.jsp的,所以index.jsp中通过request.getRemoteAddr()的方法获取的IP实际上是代理服务器的地址,并不是客户端的IP地址。

  于是可得出获得客户端真实IP地址的方法一:
publicStringgetIpAddr(HttpServletRequestrequest){
Stringip=request.getHeader("x-forwarded-for");
if(ip==null||ip.length()==0){
ip=request.getRemoteAddr();
}
returnip;
}
可是当我访问http://www.xxx.com/index.jsp/时,返回的IP地址始终是unknown,也并不是如上所示的127.0.0.1 或 192.168.1.110了,而我访问http://192.168.1.110:2046/index.jsp时,则能返回客户端的真实IP地址,写了个方法去验证。
  • <%@pageimport="java.util.*"%>
  • <tableborder=1cellspacing=0cellpadding=0align=center>
  • <tr>
  • <th>Name</th>
  • <th>Value</th>
  • </tr>
  • <%
  • EnumerationenumNames;
  • StringstrName,strValue;
  • enumNames=request.getHeaderNames();
  • while(enumNames.hasMoreElements()){
  • strName=(String)enumNames.nextElement();
  • strValue=request.getHeader(strName);
  • %>
  • <tr>
  • <td><%=strName%></td>
  • <td><%=strValue%></td>
  • </tr>
  • <%
  • }
  • %>
  • <tr>
  • </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,重启后,访问http://www.xxx.com/index.jsp/ 获得的IP是客户端的真实IP。
    于是可得出获得客户端真实IP地址的方法二:
  • publicStringgetIpAddr(HttpServletRequestrequest){
  • Stringip=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();
  • }
  • returnip;
  • }
    可是,如果通过了多级反向代理的话,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


    一、没有使用代理服务器的情况:

    REMOTE_ADDR = 您的 IP
    HTTP_VIA = 没数值或不显示
    HTTP_X_FORWARDED_FOR = 没数值或不显示

    二、使用透明代理服务器的情况:Transparent Proxies

    REMOTE_ADDR = 最后一个代理服务器 IP
    HTTP_VIA = 代理服务器 IP
    HTTP_X_FORWARDED_FOR = 您的真实 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。

    这类代理服务器还是将您的信息转发给您的访问对象,无法达到隐藏真实身份的目的。

    三、使用普通匿名代理服务器的情况:Anonymous Proxies

    REMOTE_ADDR = 最后一个代理服务器 IP
    HTTP_VIA = 代理服务器 IP
    HTTP_X_FORWARDED_FOR = 代理服务器 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。

    隐藏了您的真实IP,但是向访问对象透露了您是使用代理服务器访问他们的。

    四、使用欺骗性代理服务器的情况:Distorting Proxies

    REMOTE_ADDR = 代理服务器 IP
    HTTP_VIA = 代理服务器 IP
    HTTP_X_FORWARDED_FOR = 随机的 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。

    告诉了访问对象您使用了代理服务器,但编造了一个虚假的随机IP代替您的真实IP欺骗它。

    五、使用高匿名代理服务器的情况:High Anonymity Proxies (Elite proxies)

    REMOTE_ADDR = 代理服务器 IP
    HTTP_VIA = 没数值或不显示
    HTTP_X_FORWARDED_FOR = 没数值或不显示 ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。

    完全用代理服务器的信息替代了您的所有信息,就象您就是完全使用那台代理服务器直接访问对象。

    参考了网上的一些资料,最后自己写的获得ip地址的代码如下:

    这种方法有可能会带来问题,可是暂时只能想到这一步,以后如果有机会会做相应改正。


  • 分享到:
    评论
    1 楼 delianghe 2012-07-03  
    StringUtils.isEmpty(ip),StringUtils这个字符串是在哪里定义的?看不懂!能不能贴完整一点的代码?

    相关推荐

    Global site tag (gtag.js) - Google Analytics