码迷,mamicode.com
首页 > 其他好文 > 详细

获取用户(操作人)真实Ip

时间:2015-09-23 21:00:56      阅读:146      评论:0      收藏:0      [点我收藏+]

标签:

1:获取本地IP(Local)

若应用部署到服务器端则获取的IP为服务器地址

private static String getWebServerIp() {        

  StringBuilder ipString = new StringBuilder();        

  Enumeration<NetworkInterface> netInterfaces = null;        

  InetAddress ip = null;        

  try {            

    netInterfaces = NetworkInterface.getNetworkInterfaces();            

    while (netInterfaces.hasMoreElements()) {

                NetworkInterface ni = netInterfaces.nextElement();

                Enumeration<InetAddress> ips = ni.getInetAddresses();

                while (ips.hasMoreElements()) {

                    ip = ips.nextElement();

                    if (ip != null && !ip.isLoopbackAddress()) {

                        if (ip.getHostAddress() != null && ip.getHostAddress().indexOf(":") < 0) {

                            ipString.append(ip.getHostAddress()).append(" ");

                        }

                    }

                }

            }

        } catch (Exception e) {

            log.error("get local ip error", e);

        }

        return ipString.toString();

}

2:获取用户真实Ip

public class GetIpAction extends BaseAction {

   public  String getRemoteIpNew() {

   Result result = new Result();

        if (request == null) {

            return null;

        }

        /**          * 来源1 用于使用反向代理的运行环境,如生产,测试

         * 来源2 用于本机开发环境

         */

        String ip = null;

        // 来源1 优先从x-forwarded-for 中抓取ip

        String ipOld = request.getHeader("j-forwarded-for");

        System.out.println("IpWebUtils->getRemoteIpNew j-forwarded-for:" + ipOld);

        if (ipOld == null || ipOld.length() == 0 || "unknown".equalsIgnoreCase(ipOld)) {

            ipOld = request.getHeader("x-forwarded-for");

            System.out.println("IpWebUtils->getRemoteIpNew x-forwarded-for:" + ipOld);

        }

        if (StringUtils.isBlank(ipOld) || "unknown".equalsIgnoreCase(ipOld)) {

            //来源2 ,开发环境使用

            ipOld = request.getRemoteAddr();

            System.out.println("IpWebUtils->getRemoteIpNew getRemoteAddr:" + ipOld);

        }

        if (ipOld.contains(",")) {

            //使用代理的情况,如 12.113.55.66,15.23.41.52

            String proxyIp[] = ipOld.split(",");

            //1.使用代理的正常情况,xff结构为 [用户ip,proxy1,proxy2,...proxyN,loadbalanceIp]

            //2.xff伪造的可能情况 [proxy1,proxy2,...proxyN,用户ip,loadbalanceIp]

            //3. 从后向前抓取第一个外网ip作为用户ip

            //4. 为防止xff伪造攻击, 可能造成部分使用代理的用户出现验证码

            for (int i = proxyIp.length - 1; i >= 0; i--) {

                String tempIp = proxyIp[i];

                if (!inLAN(tempIp)) {

                    //第一个非局域网ip作为用户ip

                    ip = tempIp;

                    break;

                }

            }

            if (ip == null) {

                //全部ip均为内网ip取第一个内网ip作为用户ip

                ip = proxyIp[0];

            }

        } else {

             ip = ipOld;

        }

        ip = ip.trim();

        //有些变态的情况带着端口

        result.addDefaultModel("message", ip);

        //return ip.contains(":") ? ip.split(":")[0] : ip;

        toVm(result);

  return SUCCESS;

}

该函数通过分析获取到不同种类的Ip字符串(通过Http请求头获取)来区分不同种类的网络模型。

以下两个方法为上述函数中用到的方法。

1:判断获取到的地址为哪种类型的Ip格式。

private static boolean inLAN(String tempId) {

     tempId = StringUtils.trimToEmpty(tempId);

     int[] ints = divideIp(tempId);      //非法ip

     if (ints.length < 4) {

         return true;

     }

     if (ints[0] == 10) {          //a类ip

         return true;

     }

     if (ints[0] == 192 && ints[1] == 168 && ints[2] >= 0 && ints[2] <= 255) {

           //c类ip

          return true;      }

     if (ints[0] == 172 && ints[1] >= 16 && ints[1] <= 31) {

         //b类ip

         return true;      }

     if ("127.0.0.1".equals(tempId)) {

         //本机地址

         return true;

     }

     return false;

 }

2.拆分获取到的Ip字符串

private static int[] divideIp(String tempId) {

     String[] strs = tempId.split("\\.");

     int[] result = new int[strs.length];

     for (int i = 0; i < strs.length; i++) {

         try {

             result[i] = Integer.parseInt(StringUtils.trimToEmpty(strs[i]));

         } catch (Exception e) {

 

         }

     }

     return result;

}

此种方法部署到测试环境中时,获取到的Ip地址均为同一个地址。由于不能实际验证,怀疑获取到的Ip地址为内网访问处于外网测试环境服务器的Ip。访问测试环境需要通过地址转换,所有访问测试环境服务器的Ip均被替换成同样的一个Ip。该问题在将代码上线后不存在。

上线后获取的x-forward-for Ip地址为用户真实Ip地址,两个proxy代理地址均为Null,remote-Ip为127.0.0.1。

具体为什么会这样原因还不是十分清楚,欢迎大神指导讨论。

获取用户(操作人)真实Ip

标签:

原文地址:http://www.cnblogs.com/Isaca/p/4833392.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!