• 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;  
        }
    此时,正常情况之下可以获取客户端真实的IP。需要注意的是对于服务器端采用负载的形式,需要配置保存x-forwarded-for。

    转载地址:http://www.cnblogs.com/xiaoxing/p/6565573.html

  • 相关阅读:
    再论使用Oracle Instant Client连接Oracle
    再谈业务逻辑架构模式(事务脚本,表模块,活动记录,领域模型)
    业务逻辑架构模式(事务脚本,表模块,活动记录,领域模型)
    .net程序集组成与内存布局
    多参的实现原理
    起点
    Windows1[头文件]
    C++中构造函数、析构函数、拷贝构造函数详解
    PHP 开发工具
    写点东西顺便吐槽(很弱很弱的技术文)
  • 原文地址:https://www.cnblogs.com/archermeng/p/7537061.html
Copyright © 2020-2023  润新知