欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-10-28 12:37:40
这篇文章主要介绍了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;
}

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