SpringBoot如何通过Nginx代理获取真实IP

这篇具有很好参考价值的文章主要介绍了SpringBoot如何通过Nginx代理获取真实IP。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

springboot作为后台代码,获取到的登录IP是前台的代理服务器地址,并不是用户的真实IP地址,让我们在做统计的时候无从下手。下面是一个后台获取IP地址的类,本质上没有什么问题,问题在于,Nginx给你的就是一个代理之后的地址,所以你当然获取不到真实的地址了。

package com.**.common.core.utils.ip;

import java.net.InetAddress;
import java.net.UnknownHostException;
import javax.servlet.http.HttpServletRequest;
import com.**.common.core.utils.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;

/**
 * 获取IP方法
 * 
 * @author Hxhh
 */
public class IpUtils
{
    /**
     * 获取客户端IP
     * 
     * @param request 请求对象
     * @return IP地址
     */
    public static String getIpAddr(HttpServletRequest request)
    {
        if (request == null)
        {
            return "unknown";
        }
        String ip = request.getHeader("x-forwarded-for");
        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("X-Forwarded-For");
        }
        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("X-Real-IP");
        }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getRemoteAddr();
        }

        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : getMultistageReverseProxyIp(ip);
    }

    public static String getIpAddr(ServerHttpRequest request) {
        HttpHeaders headers = request.getHeaders();
        String ip = headers.getFirst("x-forwarded-for");
        if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
            // 多次反向代理后会有多个ip值,第一个ip才是真实ip
            if (ip.indexOf(",") != -1) {
                ip = ip.split(",")[0];
            }
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("X-Real-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddress().getAddress().getHostAddress();
        }
        return ip;
    }


    /**
     * 检查是否为内部IP地址
     * 
     * @param ip IP地址
     * @return 结果
     */
    public static boolean internalIp(String ip)
    {
        byte[] addr = textToNumericFormatV4(ip);
        return internalIp(addr) || "127.0.0.1".equals(ip);
    }

    /**
     * 检查是否为内部IP地址
     * 
     * @param addr byte地址
     * @return 结果
     */
    private static boolean internalIp(byte[] addr)
    {
        if (StringUtils.isNull(addr) || addr.length < 2)
        {
            return true;
        }
        final byte b0 = addr[0];
        final byte b1 = addr[1];
        // 10.x.x.x/8
        final byte SECTION_1 = 0x0A;
        // 172.16.x.x/12
        final byte SECTION_2 = (byte) 0xAC;
        final byte SECTION_3 = (byte) 0x10;
        final byte SECTION_4 = (byte) 0x1F;
        // 192.168.x.x/16
        final byte SECTION_5 = (byte) 0xC0;
        final byte SECTION_6 = (byte) 0xA8;
        switch (b0)
        {
            case SECTION_1:
                return true;
            case SECTION_2:
                if (b1 >= SECTION_3 && b1 <= SECTION_4)
                {
                    return true;
                }
            case SECTION_5:
                switch (b1)
                {
                    case SECTION_6:
                        return true;
                }
            default:
                return false;
        }
    }

    /**
     * 将IPv4地址转换成字节
     * 
     * @param text IPv4地址
     * @return byte 字节
     */
    public static byte[] textToNumericFormatV4(String text)
    {
        if (text.length() == 0)
        {
            return null;
        }

        byte[] bytes = new byte[4];
        String[] elements = text.split("\\.", -1);
        try
        {
            long l;
            int i;
            switch (elements.length)
            {
                case 1:
                    l = Long.parseLong(elements[0]);
                    if ((l < 0L) || (l > 4294967295L))
                    {
                        return null;
                    }
                    bytes[0] = (byte) (int) (l >> 24 & 0xFF);
                    bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF);
                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
                    bytes[3] = (byte) (int) (l & 0xFF);
                    break;
                case 2:
                    l = Integer.parseInt(elements[0]);
                    if ((l < 0L) || (l > 255L))
                    {
                        return null;
                    }
                    bytes[0] = (byte) (int) (l & 0xFF);
                    l = Integer.parseInt(elements[1]);
                    if ((l < 0L) || (l > 16777215L))
                    {
                        return null;
                    }
                    bytes[1] = (byte) (int) (l >> 16 & 0xFF);
                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
                    bytes[3] = (byte) (int) (l & 0xFF);
                    break;
                case 3:
                    for (i = 0; i < 2; ++i)
                    {
                        l = Integer.parseInt(elements[i]);
                        if ((l < 0L) || (l > 255L))
                        {
                            return null;
                        }
                        bytes[i] = (byte) (int) (l & 0xFF);
                    }
                    l = Integer.parseInt(elements[2]);
                    if ((l < 0L) || (l > 65535L))
                    {
                        return null;
                    }
                    bytes[2] = (byte) (int) (l >> 8 & 0xFF);
                    bytes[3] = (byte) (int) (l & 0xFF);
                    break;
                case 4:
                    for (i = 0; i < 4; ++i)
                    {
                        l = Integer.parseInt(elements[i]);
                        if ((l < 0L) || (l > 255L))
                        {
                            return null;
                        }
                        bytes[i] = (byte) (int) (l & 0xFF);
                    }
                    break;
                default:
                    return null;
            }
        }
        catch (NumberFormatException e)
        {
            return null;
        }
        return bytes;
    }

    /**
     * 获取IP地址
     * 
     * @return 本地IP地址
     */
    public static String getHostIp()
    {
        try
        {
            return InetAddress.getLocalHost().getHostAddress();
        }
        catch (UnknownHostException e)
        {
        }
        return "127.0.0.1";
    }

    /**
     * 获取主机名
     * 
     * @return 本地主机名
     */
    public static String getHostName()
    {
        try
        {
            return InetAddress.getLocalHost().getHostName();
        }
        catch (UnknownHostException e)
        {
        }
        return "未知";
    }

    /**
     * 从多级反向代理中获得第一个非unknown IP地址
     *
     * @param ip 获得的IP地址
     * @return 第一个非unknown IP地址
     */
    public static String getMultistageReverseProxyIp(String ip)
    {
        // 多级反向代理检测
        if (ip != null && ip.indexOf(",") > 0)
        {
            final String[] ips = ip.trim().split(",");
            for (String subIp : ips)
            {
                if (false == isUnknown(subIp))
                {
                    ip = subIp;
                    break;
                }
            }
        }
        return ip;
    }

    /**
     * 检测给定字符串是否为未知,多用于检测HTTP请求相关
     *
     * @param checkString 被检测的字符串
     * @return 是否未知
     */
    public static boolean isUnknown(String checkString)
    {
        return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString);
    }
}

那么如何识别客户端的真实IP呢,需要通过两种方式去判断:

1、没有代理
如果只是普通的web项目的话,通过 request.getRemoteAddr(); (HttpServletRequest 类型) 即可获取到客户端的真实IP

2、Nginx代理
在有代理的情况下,由于任何请求首先经过Nginx,故通过request.getRemoteAddr()获取的其实是Nginx的IP,并非真实的客户端IP;此时通过x-forwarded-for获取的IP为:"客户端,代理1,代理2,..."或者"伪造IP,客户端,代理1,代理2,...",故不能获取到准确的客户端IP,此时需要配置Nginx TCP客户端连接的真实IP,通过代理配置获取真实IP,可以通过$remote_addr获取客户端IP,Nginx配置如下:

location / {
   //追加如下代码
   proxy_set_header X-Real-IP $remote_addr;
   proxy_set_header Host $host;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 
}


 然后服务端通过: request.getHeader("X-Real-IP");    即可获取到客户端的真实IP文章来源地址https://www.toymoban.com/news/detail-797915.html

到了这里,关于SpringBoot如何通过Nginx代理获取真实IP的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • nginx如何获取真实客户端ip

    nginx作为反向代理服务器,即代理我们的服务端,下面介绍下如何配置nginx获取真实的客户端ip 1、配置nginx.con 2、在java程序中可以通过如下方式获取: 这样就可以打印出真实ip了!即request.getHeader(\\\"X-Real-IP\\\")的值 引用: 查看端口占用及释放所占用的端口_查询谷歌浏览器的端口

    2024年02月11日
    浏览(53)
  • nestjs:nginx反向代理服务器后如何获取请求的ip地址

    问题:         如题 参考:         nodejs+nginx获取真实ip-腾讯云开发者社区-腾讯云         「转」从限流谈到伪造 IP nginx remote_addr          解决办法: 1.设置nginx         对于代理部分,对http header添加Host、X-Real-IP、X-Forwarded-For(最重要)          2.nestjs使用

    2024年02月13日
    浏览(56)
  • 如何通过nginx反向代理实现不同域名映射到同一台服务器的相同端口

    要在Nginx中实现不同域名映射到同一台服务器的相同端口,您可以使用Nginx的代理转发技术。 首先,您需要了解Nginx的代理转发工作原理。Nginx的代理转发是指在代理服务器(proxy server)收到一个请求时,先将请求转发给目标服务器(target server),然后将服务器的响应返回给代

    2024年02月13日
    浏览(61)
  • nginx配置获取真实ip

    要想在应用中获取到真实IP,取决于各个转发节点的传递配置, 第一、要确定客户端使用哪个请求头传递IP地址 第二、第一转发点, proxy_set_header field value value是变量值,来源于请求方 field是变量名,是要发给下一站的变量 注意这个顺序,set设置要发往下一站的变量,紧接着

    2024年02月11日
    浏览(49)
  • 如何通过nginx代理实现外网访问内网mysql或oracle数据库

            项目开发部署中经常会遇到MySQL或Oracle数据库安装在内网,而我们的应用服务只能部署在外网,如果实现外网服务访问连接内网的数据库呢?本次介绍如何通过Nginx配置实现外网访问内网数据库。 1、前置机服务器         首先要保证有一台前置机服务器既可以访

    2024年02月15日
    浏览(44)
  • nginx 获取客户端真实IP

    网站接入Web应用防火墙WAF(Web Application Firewall)后,访问请求在到达源站服务器之前,需要经过WAF的代理转发。这种情况下,源站服务器可以通过解析回源请求中的X-Forwarded-For记录,获取客户端的真实IP。 WAF在将客户端的访问请求转发到下一环节的服务器时,会在HTTP的请求头

    2023年04月09日
    浏览(46)
  • nginx配置获取客户端的真实ip

    场景描述: 访问路径: A机器 - B机器的 -C虚拟机 : A机器为客户端用户,本地地址为 192.168.0.110 B机器为服务端反向代理服务器 本地地址为192.168.0.128 –(192.168.56.1) C机器为B主机安装的linux虚拟机,并安装了nginx ,本地ip为**(192.168.56.10)** 从侧面反映了反向代理的好处,直

    2024年02月05日
    浏览(44)
  • nginx获取客户端真实ip

    在nginx中获取客户端真实IP的方法有多种,以下是其中两种常用的方法: 使用nginx的access_log模块记录请求日志,并在日志中包含客户端的真实IP信息。例如: 在上述配置中,通过使用http_x_forwarded_for字段来获取客户端的真实IP地址。如果该字段不存在或不合法,则使用remote_ad

    2024年02月16日
    浏览(49)
  • Java-通过IP获取真实地址

    最近写了一个日志系统,需要通过访问的 IP 地址来获取真实的地址,并且存到数据库中,我也是在网上看了一些文章,遂即整理了一下供大家参考。 这个是获取正确 IP 地址的方法,可以直接使用的。 通过以上方法你可以获取到访问者的 IP 地址,只有获取到了 IP 地址,才能

    2024年02月15日
    浏览(51)
  • Nginx(二十) 获取真实客户端IP

            客户端在访问互联网应用服务器时,与真实的应用服务器之间会因为有多层反向代理,而导致真实应用服务器获取的仅是最近一层的反向代理服务器 IP。为使 Nginx 后端的上游服务器可以获得真实客户端 IP,Nginx 提供了 ngx_http_realip_module 模块用以实现真实客户端

    2024年01月16日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包