Java Web 获取客户端真实IP

Java Web 获取客户端真实IP

发生的场景:服务器端接收客户端请求的时候,一般需要进行签名验证,客户端IP限定等情况,在进行客户端IP限定的时候,需要首先获取该真实的IP。一般分为两种情况:

方式一、客户端未经过代理,直接访问服务器端(nginx,squid,haproxy);

方式二、客户端通过多级代理,最终到达服务器端(nginx,squid,haproxy);

  客户端请求信息都包含在HttpServletRequest中,可以通过方法getRemoteAddr()获得该客户端IP。此时如果在使用方式一形式,可以直接获得该客户端真实IP。而如果是方式二中通过代理的形式,此时经过多级反向的代理,通过方法getRemoteAddr()得不到客户端真实IP,可以通过x-forwarded-for获得转发后请求信息。当客户端请求被转发,IP将会追加在其后并以逗号隔开,例如:10.47.103.13,4.2.2.2,10.96.112.230。

请求中的参数:

request.getHeader("x-forwarded-for") : 10.47.103.13,4.2.2.2,10.96.112.230

request.getHeader("X-Real-IP") : 10.47.103.13

request.getRemoteAddr():10.96.112.230

客户端访问经过转发,IP将会追加在其后并以逗号隔开。最终准确的客户端信息为:

  • x-forwarded-for 不为空,则为逗号前第一个IP ;
  • X-Real-IP不为空,则为该IP ;
  • 否则为getRemoteAddr() ;

代码示例:

    /**
     * 获取用户真实IP地址,不使用request.getRemoteAddr()的原因是有可能用户使用了代理软件方式避免真实IP地址,
     * 可是,如果通过了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP值
     *
     * @return ip
     */
    private String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        System.out.println("x-forwarded-for ip: " + ip);
        if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
            // 多次反向代理后会有多个ip值,第一个ip才是真实ip
            if( ip.indexOf(",")!=-1 ){
                ip = ip.split(",")[0];
            }
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
            System.out.println("Proxy-Client-IP ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
            System.out.println("WL-Proxy-Client-IP ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
            System.out.println("HTTP_CLIENT_IP ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            System.out.println("HTTP_X_FORWARDED_FOR ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
            System.out.println("X-Real-IP ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
            System.out.println("getRemoteAddr ip: " + ip);
        }
        System.out.println("获取客户端ip: " + ip);
        return ip;
    }

上面代码中这些请求头的大致意思:

  • X-Forwarded-For

这是一个 Squid 开发的字段,只有在通过了HTTP代理或者负载均衡服务器时才会添加该项。

格式为X-Forwarded-For:client1,proxy1,proxy2,一般情况下,第一个ip为客户端真实ip,后面的为经过的代理服务器ip。现在大部分的代理都会加上这个请求头。

  • Proxy-Client-IP/WL- Proxy-Client-IP

这个一般是经过apache http服务器的请求才会有,用apache http做代理时一般会加上Proxy-Client-IP请求头,而WL-Proxy-Client-IP是他的weblogic插件加上的头。

  • HTTP_CLIENT_IP

有些代理服务器会加上此请求头。

  • X-Real-IP 
    nginx代理一般会加上此请求头。

如果使用的是Druid连接池,可以参考使用:com.alibaba.druid.util.DruidWebUtils#getRemoteAddr方法,但这个是经过多级代理的IP地址,需要自己处理下获取第一个。

有几点要注意

    1. 这些请求头都不是http协议里的标准请求头,也就是说这个是各个代理服务器自己规定的表示客户端地址的请求头。如果哪天有一个代理服务器软件用oooo-client-ip这个请求头代表客户端请求,那上面的代码就不行了。
    2. 这些请求头不是代理服务器一定会带上的,网络上的很多匿名代理就没有这些请求头,所以获取到的客户端ip不一定是真实的客户端ip。代理服务器一般都可以自定义请求头设置。
    3. 即使请求经过的代理都会按自己的规范附上代理请求头,上面的代码也不能确保获得的一定是客户端ip。不同的网络架构,判断请求头的顺序是不一样的。
    4. 最重要的一点,请求头都是可以伪造的。如果一些对客户端校验较严格的应用(比如投票)要获取客户端ip,应该直接使用ip=request.getRemoteAddr(),虽然获取到的可能是代理的ip而不是客户端的ip,但这个获取到的ip基本上是不可能伪造的,也就杜绝了刷票的可能。(有分析说arp欺骗+syn有可能伪造此ip,如果真的可以,这是所有基于TCP协议都存在的漏洞),这个ip是tcp连接里的ip。

参考 
http://blog.csdn.net/sgx425021234/article/details/19043459 
http://blog.csdn.net/fengwind1/article/details/51992528

https://www.cnblogs.com/xiaoxing/p/6565573.html

https://blog.csdn.net/youanyyou/article/details/79406454

原文地址:https://www.cnblogs.com/hui-run/p/10372338.html

时间: 2024-10-31 12:53:03

Java Web 获取客户端真实IP的相关文章

Java正确获取客户端真实IP方法整理

在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的.但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实IP地址了. 如果使用了反向代理软件,将http://192.168.1.110:2046/的URL反向代理为http://www.abc.com/的URL时,用request.getRemoteAddr()方法获取的IP地址是:127.0.0.1或192.168.1.110,而并不是客户端的真实IP

获取客户端真实IP地址

1.需要引入log4j-1.2.14.jar package org.ydd.test; import java.util.Enumeration; import javax.servlet.http.HttpServletRequest; import org.apache.log4j.Logger; /** * @author coco * @version * 获取IP4 */ public class IP4 { private static final Logger log = Log

nginx在varnish后端做负载均衡,后端tomca获取客户端真实IP

nginx在varnish后端做负载均衡,后端tomca获取客户端真实IP 1.设置nginx配置文件    首先要确定nginx做负载均衡,在安装时把http_realip_module 安装上了.    查看方法: /usr/local/nginx/sbin/nginx -V   配置nginx.conf    vim /usr/local/nginx/conf/nginx.conf   加入 set_real_ip_from 192.168.88.131;      重新加载nginx:

asp网络编程:ASP如何获取客户端真实IP地址

要想透过代理服务器取得客户端的真实IP地址,就要使用 Request.ServerVariables("HTTP_X_FORWARDED_FOR") 来读取.不过要注意的事,并不是每个代理服务器都能用 Request.ServerVariables("HTTP_X_FORWARDED_FOR") 来读取客户端的真实 IP,有些用此方法读取到的仍然是代理服务器的IP.还有一点需要注意的是:如果客户端没有通过代理服务器来访问,那么用 Request.ServerVari

获取客户端真实ip

1 // 获取客户端真实ip() 2 protected function getIP() 3 { 4 global $ip; 5 if (getenv("HTTP_CLIENT_IP")) 6 $ip = getenv("HTTP_CLIENT_IP"); 7 else if(getenv("HTTP_X_FORWARDED_FOR")) 8 $ip = getenv("HTTP_X_FORWARDED_FOR"); 9 e

解决haproxy代理nginx获取客户端真实ip问题

问题背景: 我们公司之前由于DDOS攻击导致网络出口受影响,经过了解,流量进入亚马逊是不收钱的,而且不限流量,为了加强防范网络攻击对业务造成影响,在亚马逊部署一套haproxy代理,把部分业务迁移试用. 为了使用nginx能获取到客户端的ip地址,在haproxy中配置option httpclose和option forwardfor,nginx配置set_real_ip_from x.x.x.x;和real_ip_header X-Forwarded-For;(其中x.x.x.x是hapro

Tomcat中获取客户端真实IP及协议

获取客户端真实IP ServletRequest接口提供了getRemoteAddr方法用于获取客户端IP,但是当客户端通过代理服务器访问后端服务器的时候,服务器调用getRemoteAddr方法会返回最近的代理服务器的IP而非客户端真实IP.这种情况下通常是使用X-Forwarded-For请求头来获取客户端真实IP. X-Forwarded-For简称XFF头,它保存了客户端和各级代理服务器的IP,只有在通过了HTTP正向代理服务器或者反向代理服务器时才会添加该项,一般格式如下:X-Forw

Java面试-如何获取客户端真实IP

在进行一些小游戏开发时,我们经常比较关注的一个功能便是分享.针对分享,我们希望能根据各个城市或者地区,能有不同的分享文案,辨识地区的功能如果由服务器来完成的话,我们就需要知道客户端的真实IP.今天我们就来看看服务器是如何获取到客户端的真实IP的. nginx配置 首先,一个请求肯定是可以分为请求头和请求体的,而我们客户端的IP地址信息一般都是存储在请求头里的.如果你的服务器有用Nginx做负载均衡的话,你需要在你的location里面配置X-Real-IP和X-Forwarded-For请求头:

使用Java技术获取客户端的IP地址

今天发文一篇较为简单,且文档满天飞的获取IP地址的java代码,可能很多小白们不一定能找到完整兼容的方法,故在此送给小白们一份干货. 此文也是为了接下来的时间里,我将会写一篇使用HTML5技术扫描PC二维码且在WAP端实现可上传图片或视频的文档,这里会运用到根据参数动态生成二维码和传输文件的技术,也会应用到ip及端口的东西. 下面是运用java代码判断当前客服端IP地址的逻辑: private String getInternetIp(HttpServletRequest request) {