SpringBoot获取不到用户真实IP的解决方法
作者:BivinCode
最近遇到个问题,项目部署后发现服务端无法获取到客户端真实的IP地址,本文就来介绍一下这个问题的解决方法,感兴趣的可以了解一下
今天周六,Binvin来总结一下上周开发过程中遇到的一个小问题,项目部署后发现服务端无法获取到客户端真实的IP地址,这是怎么回事呢?给我都整懵逼了,经过短暂的思考,我发现了问题的真凶,那就是我们使用了Nginx作的请求转发,这才导致了获取不到客户端真实的IP地址,害,看看我是怎么解决的吧!
问题原因
客户端请求数据时走的是Nginx反向代理,默认情况下客户端的真实IP地址会被其过滤,使得SpringBoot程序无法直接获得真实的客户端IP地址,获取到的都是Nginx的IP地址。
解决方案:
通过更改Nginx配置文件将客户端真实的IP地址加到请求头中,这样就能正常获取到客户端的IP地址了,下面我一步步带你看看如何配置和获取。
修改Nginx配置文件
在需要做请求转发的配置里添加下面的配置
#这个参数设置了HTTP请求头的Host字段,host表示请求的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.conf中的server如下所示
server { listen 443 ssl; server_name xxx.com; ssl_certificate "ssl证书pem文件"; ssl_certificate_key "ssl证书key文件"; ssl_session_timeout 5m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; ssl_prefer_server_ciphers on; location / { root 前端html文件目录; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } # 关键在下面这个配置,上面的配置自己根据情况而定就行 location /hello{ proxy_pass http://127.0.0.1:8090; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
SpringBoot代码实现
第一种方式:在代码中直接通过X-Forwarded-For获取到真实IP地址
@Slf4j public class CommonUtil { /** * <p> 获取当前请求客户端的IP地址 </p> * * @param request 请求信息 * @return ip地址 **/ public static String getIp(HttpServletRequest request) { if (request == null) { return null; } String unknown = "unknown"; // 使用X-Forwarded-For就能获取到客户端真实IP地址 String ip = request.getHeader("X-Forwarded-For"); log.info("X-Forwarded-For:" + ip); if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); log.info("Proxy-Client-IP:" + ip); } if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); log.info("WL-Proxy-Client-IP:" + ip); } if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_X_FORWARDED_FOR"); log.info("HTTP_X_FORWARDED_FOR:" + ip); } if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_X_FORWARDED"); log.info("HTTP_X_FORWARDED:" + ip); } if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_X_CLUSTER_CLIENT_IP"); log.info("HTTP_X_CLUSTER_CLIENT_IP:" + ip); } if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_CLIENT_IP"); log.info("HTTP_CLIENT_IP:" + ip); } if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_FORWARDED_FOR"); log.info("HTTP_FORWARDED_FOR:" + ip); } if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_FORWARDED"); log.info("HTTP_FORWARDED:" + ip); } if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_VIA"); log.info("HTTP_VIA:" + ip); } if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) { ip = request.getHeader("REMOTE_ADDR"); log.info("REMOTE_ADDR:" + ip); } if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); log.info("getRemoteAddr:" + ip); } return ip; }
第二种方式:在application.yml文件中加以下配置,直接通过request.getRemoteAddr()并可以获取到真实IP
server: port: 8090 tomcat: #Nginx转发 获取客户端真实IP配置 remoteip: remote-ip-header: X-Real-IP protocol-header: X-Forwarded-Proto
到此这篇关于SpringBoot获取不到用户真实IP的解决方法的文章就介绍到这了,更多相关SpringBoot获取不到用户真实IP内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!