Java获取客户端真实IP地址过程解析

 更新时间:2020年01月16日 11:04:42   作者:楼兰的胡杨  
这篇文章主要介绍了Java获取客户端真实IP地址过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

这篇文章主要介绍了Java获取客户端真实IP地址过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

业务背景

服务器端接收客户端请求的时候,一般需要进行签名验证,客户端IP限定等拦截,在进行IP限定的时候就需要获取客户端真实的IP。

基础知识

访问服务端的方式一般分为两种:

未经过代理,直接访问服务器端;

通过多级代理,最终到达服务器端(nginx,squid,haproxy)。

客户端请求信息都包含在HttpServletRequest中,对于第一种访问方式可以通过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() ;

相关请求头的解释:

X-Forwarded-For 记录一个请求从客户端出发到目标服务器过程中经历的代理,或者负载平衡设备的IP。这是由缓存代理软件 Squid 引入,用来表示 HTTP 请求端真实 IP,现在已经成为事实上的标准,被各大 HTTP 代理、负载均衡等转发服务广泛使用,并被写入 RFC 7239(Forwarded HTTP Extension)标准之中。格式为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代理一般会加上此请求头。

获取客户端真实IP地址

源码:

/**
 * 获取客户端的IP地址<br/>
 * 注意本地测试访问项目地址时,浏览器请求不要用 localhost,请用本机IP;否则,取不到 IP
 *
 * @author east7
 * @date 2019年12月03日
 * @return String 真实IP地址
 */
public static String getClientIpAddress(HttpServletRequest request) {
  // 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址
  String headerName = "x-forwarded-for";
  String ip = request.getHeader(headerName);
  if (null != ip && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
    // 多次反向代理后会有多个IP值,第一个IP才是真实IP,它们按照英文逗号','分割
    if (ip.indexOf(",") != -1) {
      ip = ip.split(",")[0];
    }
  }
  if (checkIp(ip)) {
    headerName = "Proxy-Client-IP";
    ip = request.getHeader(headerName);
  }
  if (checkIp(ip)) {
    headerName = "WL-Proxy-Client-IP";
    ip = request.getHeader(headerName);
  }
  if (checkIp(ip)) {
    headerName = "HTTP_CLIENT_IP";
    ip = request.getHeader(headerName);
  }
  if (checkIp(ip)) {
    headerName = "HTTP_X_FORWARDED_FOR";
    ip = request.getHeader(headerName);
  }
  if (checkIp(ip)) {
    headerName = "X-Real-IP";
    ip = request.getHeader(headerName);
  }
  if (checkIp(ip)) {
    headerName = "remote addr";
    ip = request.getRemoteAddr();
    // 127.0.0.1 ipv4, 0:0:0:0:0:0:0:1 ipv6
    if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) {
      //根据网卡取本机配置的IP
      InetAddress inet = null;
      try {
        inet = InetAddress.getLocalHost();
      } catch (UnknownHostException e) {
        e.printStackTrace();
      }
      ip = inet.getHostAddress();
    }
  }
  logger.info("getClientIp IP is " + ip + ", headerName = " + headerName);
  return ip;
}
private static boolean checkIp(String ip) {
  if (null == ip || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
    return true;
  }
  return false;
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 解决SpringMVC同时接收Json和Restful时Request里有Map的问题

    解决SpringMVC同时接收Json和Restful时Request里有Map的问题

    今天小编就为大家分享一篇解决SpringMVC同时接收Json和Restful时Request里有Map的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-08-08
  • 浅谈java中String StringBuffer StringBuilder的区别

    浅谈java中String StringBuffer StringBuilder的区别

    下面小编就为大家带来一篇浅谈java中String StringBuffer StringBuilder的区别。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-06-06
  • 深入同步访问共享的可变数据分析

    深入同步访问共享的可变数据分析

    本篇文章是对同步访问共享的可变数据进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • Java8中接口的新特性使用指南

    Java8中接口的新特性使用指南

    接口改动一下就要修改对应的实现类,为了兼容老接口,Java8新增了默认方法和静态方法,下面这篇文章主要给大家介绍了关于Java8中接口新特性的相关资料,需要的朋友可以参考下
    2021-11-11
  • Java架构师的5大基本能力你知道吗

    Java架构师的5大基本能力你知道吗

    这篇文章主要为大家介绍了Java架构师的基本能力,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助<BR>
    2022-01-01
  • classpath和classpath*的区别详解

    classpath和classpath*的区别详解

    这篇文章主要为大家介绍了classpath和classpath*的区别详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • 如何对Mysql数据表查询出来的结果进行排序

    如何对Mysql数据表查询出来的结果进行排序

    这篇文章主要介绍了如何对Mysql数据表查询出来的结果进行排序问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08
  • JavaGUI实现随机单词答题游戏

    JavaGUI实现随机单词答题游戏

    这篇文章主要为大家详细介绍了JavaGUI实现随机单词答题游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-12-12
  • SpringBoot文件访问映射如何实现

    SpringBoot文件访问映射如何实现

    这篇文章主要介绍了SpringBoot文件访问映射如何实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • 关于JSONObject.toJSONString出现地址引用问题

    关于JSONObject.toJSONString出现地址引用问题

    这篇文章主要介绍了关于JSONObject.toJSONString出现地址引用问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03

最新评论