一、原因分析
客户端请求通过Nginx反向代理,客户端的真实IP地址会被其过滤,使得SpringBoot程序无法直接获得真实的客户端IP地址,实际获取的是nginx服务的ip
二、解决方案
#设置Host,Nginx会将请求的Host头信息传递给后端服务。
proxy_set_header Host $host;
#设置HTTP请求头的X−Real−IP字段,remote_addr表示客户端的IP地址。通过这个设置,Nginx会将客户端的真实IP地址传递给后端服务
proxy_set_header X-Real-IP $remote_addr;
#设置HTTP请求头的 X-Forwarded-For字段,"X-Forwarded-For"是一个标准的HTTP请求头,用于表示HTTP请求经过的代理服务器链路信息,proxy_add_x_forwarded_for表示添加额外的服务器链路信息。
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
接下来在你的nginx配置文件中的反向到后端的配置里加入上述代码即可
location ^~/api/ {
proxy_pass 你的后端springboot服务IP:端口;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
三、后端代码,写一个方法示例
public static String getClientIp(HttpServletRequest request) {
String ipAddress = request.getHeader("X-Forwarded-For");
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("WL-Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("HTTP_X_FORWARDED");
}
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("HTTP_X_CLUSTER_CLIENT_IP");
}
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("HTTP_CLIENT_IP");
}
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("HTTP_FORWARDED_FOR");
}
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("HTTP_FORWARDED");
}
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("HTTP_VIA");
}
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("REMOTE_ADDR");
}
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getRemoteAddr();
}
return ipAddress;
}
三、重启nginx,然后就可以获取到客户端的真实IP了