获取用户真正的ip地址

 我在用百度ip地址定位接口时,当把封装的ip定位的接口打war包放在服务器上时,出现获取的地址为服务器所在地的地址,
百度ip地址定位接口是可以根据你输入的ip来定位,需要用户输入ip地址是不可能的,用户也不知道他的ip地址是多少。

X-Forwarded-For
 X-Forwarded-For:简称XFF头,它代表客户端,也就是HTTP的请求端真实的IP,只有在通过了HTTP 代理或者负载均衡服务器时才会添加该项。它不是RFC中定义的标准请求头信息,在squid缓存代理服务器开发文档中可以找到该项的详细介绍。标准格式如下:X-Forwarded-For: client1, proxy1, proxy2。

产生背景
 X-Forwarded-For(XFF)是用来识别通过HTTP代理或负载均衡方式连接到Web服务器的客户端最原始的IP地址的HTTP请求头字段。 Squid 缓存代理服务器的开发人员最早引入了这一HTTP头字段,并由IETF在Forwarded-For HTTP头字段标准化草案中正式提出。
 当今多数缓存服务器的使用者为大型ISP,为了通过缓存的方式来降低他们的外部带宽,他们常常通过鼓励或强制用户使用代理服务器来接入互联网。有些情况下, 这些代理服务器是透明代理, 用户甚至不知道自己正在使用代理上网。
如果没有XFF或者另外一种相似的技术,所有通过代理服务器的连接只会显示代理服务器的IP地址(而非连接发起的原始IP地址), 这样的代理服务器实际上充当了匿名服务提供者的角色, 如果连接的原始IP地址不可得,恶意访问的检测与预防的难度将大大增加。XFF的有效性依赖于代理服务器提供的连接原始IP地址的真实性,因此, XFF的有效使用应该保证代理服务器是可信的, 比如可以通过建立可信服务器白名单的方式。

格式
 这一HTTP头一般格式如下:
 X-Forwarded-For: client1, proxy1, proxy2, proxy3
 其中的值通过一个 逗号+空格 把多个IP地址区分开, 最左边(client1)是最原始客户端的IP地址, 代理服务器每成功收到一个请求,就把请求来源IP地址添加到右边。 在上面这个例子中,这个请求成功通过了三台代理服务器:proxy1, proxy2 及 proxy3。请求由client1发出,到达了proxy3(proxy3可能是请求的终点)。请求刚从client1中发出时,XFF是空的,请求被发往proxy1;通过proxy1的时候,client1被添加到XFF中,之后请求被发往proxy2;通过proxy2的时候,proxy1被添加到XFF中,之后请求被发往proxy3;通过proxy3时,proxy2被添加到XFF中,之后请求的的去向不明,如果proxy3不是请求终点,请求会被继续转发。
鉴于伪造这一字段非常容易,应该谨慎使用X-Forwarded-For字段。正常情况下XFF中最后一个IP地址是最后一个代理服务器的IP地址, 这通常是一个比较可靠的信息来源。

使用
 在代理转发及反向代理中经常使用X-Forwarded-For 字段。

代理转发
 在代理转发的场景中,你可以通过内部代理链以及记录在网关设备上的IP地址追踪到网络中客户端的IP地址。处于安全考虑,网关设备在把请求发送到外网(因特网)前,应该去除 X-Forwarded-For 字段里的所有信息。这种情况下所有的信息都是在你的内部网络内生成,因此X-Forwarded-For字段中的信息应该是可靠的。

反向代理
 在反向代理的情况下,你可以追踪到互联网上连接到你的服务器的客户端的IP地址, 即使你的网络服务器和互联网在路由上是不可达的。这种情况下你不应该信任所有X-Forwarded-For信息,其中有部分可能是伪造的。因此需要建立一个信任白名单来确保X-Forwarded-For中哪些IP地址对你是可信的。
最后一次代理服务器的地址并没有记录在代理链中,因此只记录 X-Forwarded-For 字段是不够的。完整起见,Web服务器应该记录请求来源的IP地址以及X-Forwarded-For 字段信息。[2]

Web日志
 大多数Web服务器可以通过配置在日志中记录X-Forwarded-For。 Apache中可以非常简单地修改配置来实现,但MS IIS 6及以下的版本需要第三方软件支持来实现。IIS7用户可以从IIS官方网站获得免费的IIS相关组件来实现。

 java中使用X-Forwarded-For获取用户真正ip地址

String ipS = null;
String ipFor = request.getHeader("x-forwarded-for");
if (ipFor == null || ipFor.length() == 0 || "unknown".equalsIgnoreCase(ipFor)) {
    if (ipFor == null || ipFor.length() == 0 || "unknown".equalsIgnoreCase(ipFor)) {
        ipFor = request.getHeader("Proxy-Client-IP");
        System.out.println("Proxy-Client-IP : " + ipFor);
    }
    if (ipFor == null || ipFor.length() == 0 || "unknown".equalsIgnoreCase(ipFor)) {
        ipFor = request.getHeader("WL-Proxy-Client-IP");
        System.out.println("WL-Proxy-Client-IP : " + ipFor);
    }
    if (ipFor == null || ipFor.length() == 0 || "unknown".equalsIgnoreCase(ipFor)) {
        ipFor = request.getHeader("HTTP_CLIENT_IP");
        System.out.println("HTTP_CLIENT_IP : " + ipFor);
    }
    if (ipFor == null || ipFor.length() == 0 || "unknown".equalsIgnoreCase(ipFor)) {
        ipFor = request.getHeader("HTTP_X_FORWARDED_FOR");
        System.out.println("HTTP_X_FORWARDED_FOR : " + ipFor);
    }
    if (ipFor == null || ipFor.length() == 0 || "unknown".equalsIgnoreCase(ipFor)) {
        ipFor = request.getRemoteAddr();
        System.out.println("getRemoteAddr : " + ipFor);
    }
}else if (ipFor.length() > 15) {
    String[] ips = ipFor.split(",");
    for (int index = 0; index < ips.length; index++) {
        String strIp = ips[index];
        if (!("unknown".equalsIgnoreCase(strIp))) {
            ipS = strIp;
            break;
        }
    }
}
//
String reallyIp = (null == ip || ip.isEmpty())? ipS : ip ;
Log.info("当前ip地址为: "+reallyIp);
System.out.println("当前ip地址为: "+reallyIp);

版权声明:本文为博主原创文章,未经博主允许不得转载


关注公众号:猿小雷
获取更多文章,第一之间掌握技术。
有问题请在公众号内回复,小雷会一一回答。

这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_34638225/article/details/81261067
今日推荐