最近的一个项目的某个功能获取用户的ip地址,添加用户的系统使用记录。
我发现当我直接使用getRemoteAddr()方法从HttpServletRequet中获取用户的ip时,获取到的是服务器的ip地址,为什么会这样呢?
网上找到的答案:
“当我们通过request获取客户端IP时,自身服务器通常会为了保护信息或者负载均衡的目的,对自身服务器做反向代理。此时如果我们通过request.getRemoteAddr();可能获取到的是自身代理服务器的IP,而无法达到获取用户请求ip的目的。”
最终的解决方案:
以下整理了各个代理服务器自己开发的转发服务请求头,这些请求头都不是标准的http请求头,不一定所有的代理都会带上这些请求头,所以通过这方式只能尽可能的获取到真实ip,但不能保证一定可以获取到真实ip,而且代理服务器请求头中获取的ip是可伪造的。
参数:
nginx服务代理 | X-Real-IP |
Squid 服务代理 | X-Forwarded-For |
apache 服务代理 | Proxy-Client-IP |
weblogic 服务代理 | WL-Proxy-Client-IP |
有些代理服务器 | HTTP_CLIENT_IP |
以下是获取用户真实ip的工具类:
package com.pantech.boot.common.systemlog.util; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; /** * @author 肖政宇 * @date 2019-10-29 13:41 * 说明:客户端ip地址相关操作 */ @Component public class IpAddress { @Autowired HttpServletRequest request; /** * 获取发送请求的客户端的ip地址 * * @param request - 请求头 * @return - ip地址 */ public String getIpAddress(HttpServletRequest request) { String ip = null; //X-Forwarded-For:Squid 服务代理 String ipAddresses = request.getHeader("X-Forwarded-For"); //X-Real-IP:nginx服务代理 if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) { ipAddresses = request.getHeader("X-Real-IP"); } //Proxy-Client-IP:apache 服务代理 if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) { ipAddresses = request.getHeader("Proxy-Client-IP"); } //WL-Proxy-Client-IP:weblogic 服务代理 if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) { ipAddresses = request.getHeader("WL-Proxy-Client-IP"); } //HTTP_CLIENT_IP:有些代理服务器 if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) { ipAddresses = request.getHeader("HTTP_CLIENT_IP"); } //有些网络通过多层代理,那么获取到的ip就会有多个,一般都是通过逗号(,)分割开来,并且第一个ip为客户端的真实IP if (ipAddresses != null && ipAddresses.length() != 0) { ip = ipAddresses.split(",")[0]; } //还是不能获取到,最后再通过request.getRemoteAddr();获取 if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) { ip = request.getRemoteAddr(); } return ip; } public String getIpAddress() { return getIpAddress(request); } }
文中提到的解决方案原文地址:https://www.cnblogs.com/Mauno/p/Mauno.html
地势坤,君子以厚德载物。