SpringBoot获取不到用户真实IP的解决方法

 更新时间:2023年08月14日 09:58:22   作者: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内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 实例讲解Java并发编程之变量

    实例讲解Java并发编程之变量

    这篇文章主要介绍了实例讲解Java并发编程之变量,本文讲解了编写线程安全需要关心的共享变量和可变变量,需要的朋友可以参考下
    2015-04-04
  • 手动模拟JDK动态代理的方法

    手动模拟JDK动态代理的方法

    这篇文章主要介绍了手动模拟JDK动态代理的方法,帮助大家更好的了解和学习Java 代理的相关知识,感兴趣的朋友可以了解下
    2020-11-11
  • 详解java自定义类

    详解java自定义类

    这篇文章主要介绍了java自定义类的概念以及用法,文中讲解非常详细,实例代码帮助大家更好的理解,感兴趣的朋友可以参考下
    2020-06-06
  • Java面试题-实现复杂链表的复制代码分享

    Java面试题-实现复杂链表的复制代码分享

    这篇文章主要介绍了Java面试题-实现复杂链表的复制代码分享,小编觉得还是挺不错的,具有参考价值,需要的朋友可以了解下。
    2017-10-10
  • java volatile关键字的含义详细介绍

    java volatile关键字的含义详细介绍

    这篇文章主要介绍了java volatile关键字的含义详解的相关资料,需要的朋友可以参考下
    2016-12-12
  • spring boot定时任务接收邮件并且存储附件的方法讲解

    spring boot定时任务接收邮件并且存储附件的方法讲解

    今天小编就为大家分享一篇关于spring boot定时任务接收邮件并且存储附件的方法讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03
  • Springboot2.3.x整合Canal的示例代码

    Springboot2.3.x整合Canal的示例代码

    canal是阿里开源mysql binlog 数据组件,canal-server 才是canal的核心我们前边所讲的canal的功能,实际上讲述的就是canal-server的功能,本文给大家介绍Springboot2.3.x整合Canal的示例代码,需要的朋友可以参考下
    2022-02-02
  • 详解springboot采用多数据源对JdbcTemplate配置的方法

    详解springboot采用多数据源对JdbcTemplate配置的方法

    在本篇文章中我们给大家详细分享了springboot采用多数据源对JdbcTemplate配置的方法,有需要的朋友们可以学习参考下。
    2018-10-10
  • Java程序执行时间的2种简单方法

    Java程序执行时间的2种简单方法

    这篇文章介绍了Java程序执行时间的2种简单方法,有需要的朋友可以参考一下
    2013-09-09
  • SpringCloud Netfilx Ribbon负载均衡工具使用方法介绍

    SpringCloud Netfilx Ribbon负载均衡工具使用方法介绍

    Ribbon是Netflix的组件之一,负责注册中心的负载均衡,有助于控制HTTP和TCP客户端行为。Spring Cloud Netflix Ribbon一般配合Ribbon进行使用,利用在Eureka中读取的服务信息,在调用服务节点时合理进行负载
    2022-12-12

最新评论