1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > Java从代理服务器中获取客户端真实IP的方法

Java从代理服务器中获取客户端真实IP的方法

时间:2020-08-22 02:05:53

相关推荐

Java从代理服务器中获取客户端真实IP的方法

概要

一般在单机版的tomcat获取请求来源的ip,可以使用下面方式这么干,下文的request是HttpServletRequest对象。

String remoteAddr = request.getRemoteAddr();

但是如果了使用反向代理例如niginx,由于对客户请求的代理,此时request.getRemoteAddr()获取要么是本级地址127.0.0.1要么就是192.168.x.x这个内网地址,因为这种获取Ip的方式仅限与客户端和服务器端直接通信的方式才有效。在知乎上看到了一个很形象的反向代理图,如下所示:

反向代理对服务器做了代理,客户端是和代理进行通信。所以这种获取ip地址的信息获取到的是内网ip地址。

在nginx反向代理中,在nginx.conf 我们常常可以看到如下配置:X-Real-IP,X-Forwarded-For.

location / {root html;index index.html index.htm index.jsp;#proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_pass http://192.168.1.224;}

由于客户端和服务器端中间有个代理层的存在,所以服务器无法直接拿到客户真实的ip地址,在代理转发客户请求的时候,请求头(即Header)增加了X-FORWARDED-FOR这个属性,这个属性是追踪原来客户端和服务器端的IP地址。只有通过了Http代理或者负载均衡服务器才会有这个属性。当客户端发起请求时,将会有以下5步操作。

dns域名解析,通过域名找到ip代理服务器的TCP监听端口,nginx默认80端口,当有TCP连接后,将客户端请求经过处理发送到服务器服务器对接收到的Http数据包进行解压,解密,创建会话并处理请求服务器处理和相应请求后,将相应转发给代理服务器代理服务器将服务端的响应在转发给客户端服务器

所以整个请求中,客户端并没有和服务器端直接进行通信,所以request.getRemoteAddr()获取的是代理服务器的地址,因为服务器接收的是代理服务器发起的请求。

所以可以用下面方式获取客户端IP地址

获取Ip调用的方法

/*** 获取IP地址**/public static String getIpAddr(HttpServletRequest request){String ip = request.getHeader("X-Real-IP");if(!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip))return ip;ip = request.getHeader("X-Forwarded-For");if(!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)){int index = ip.indexOf(',');if(index != -1)return ip.substring(0, index);elsereturn ip;}if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))ip = request.getHeader("Proxy-Client-IP");if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))ip = request.getHeader("WL-Proxy-Client-IP");if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))ip = request.getHeader("HTTP_CLIENT_IP");if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))ip = request.getHeader("HTTP_X_FORWARDED_FOR");if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))ip = request.getRemoteAddr();return ip;}

相关请求头解释

String ip = request.getHeader("X-Real-IP");

X-Real-IP是Nginx用来获取用户的真实ip地址,但是有时候可能获取不到返回是UNKONWN。所以当获取不到使用下面方式进行获取:

String ip = request.getHeader("X-Forwarded-For");

X-Forwarded-For有时候可能获取不到,因为服务器不一定使用了反向代理,所以可能返回的也是UNKONWN,获取不到可以使用以下方式进行获取:

String ip = request.getHeader("Proxy-Client-IP");

Proxy-Client-IP是apache服务器定制一个请求头,这个属性只在apache服务器才可以看到。所以当服务器不是apache服务器,也会返回UNKONWN

String ip = request.getHeader("WL-Proxy-Client-IP");

WL- Proxy-Client-IP其中WL是weblogic的缩写,这通常用户weblogic服务器环境中,也可能返回UNKONWN

String ip = request.getHeader("HTTP_CLIENT_IP");

HTTP_CLIENT_IP有些代理服务器会加上此配置

String ip = request.getHeader("HTTP_X_FORWARD_FOR");

HTTP_X_FORWARD_FOR可以在nginx配置此项,一般为 HTTP_X_FORWARD_FOR $remote_addr;

看了上面的相关头解释和获取IP的方法,则可以将其集成到我们的项目中,如下采用webService接口获取IP和基于Spring MVC方式获取IP

webService获取IP

下面以scala定一个webService接口

@Path("/webService/getIp")@POSTdef getClientIp(@Context httpServletRequest: HttpServletRequest): String

实现类:

// 获取客户端的ipoverride def getClientIp(@Context httpServletRequest: HttpServletRequest): String = {var ip =""Try({ip = StringUtils.defaultIfBlank(getRemoteIP(httpServletRequest), "unknown")println("获取ip="+ip)}) match {case Success(_) => ipcase Failure(e) => {throw e}}}

SpringMVC获取IP

@PostMapping(Array("/springMvc/getIp"))def getIp(httpRequest: HttpServletRequest): String = {var ip =""Try({ip = StringUtils.defaultIfBlank(getRemoteIP(httpServletRequest), "unknown")println("获取ip="+ip)}) match {case Success(response) => ipcase Failure(e) => throw e}}

所以使用SpringMvc方式获取ip还是webService可以使用上面的案列,非常简单。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。