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

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。

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

转载于:https://www.cnblogs.com/Isaca/p/4833392.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值