Nginx 实战指南:暴露出请求的真实 IP

news2024/11/18 20:39:06

在这里插入图片描述

🔭 嗨,您好 👋 我是 vnjohn,在互联网企业担任 Java 开发,CSDN 优质创作者
📖 推荐专栏:Spring、MySQL、Nacos、Java,后续其他专栏会持续优化更新迭代
🌲文章所在专栏:Linux
🤔 我当前正在学习微服务领域、云原生领域、消息中间件等架构、原理知识
💬 向我询问任何您想要的东西,ID:vnjohn
🔥觉得博主文章写的还 OK,能够帮助到您的,感谢三连支持博客🙏
😄 代词: vnjohn
⚡ 有趣的事实:音乐、跑步、电影、游戏

目录

  • 前言
  • 用途/场景
    • 获取经纬度
    • 支付接口
    • 白名单配置
  • 实现源码
    • 请求工具类
    • Nginx 代理配置
    • 小结
  • 总结

前言

在工作中,经常会用用户实际请求的 IP 地址,当需要记录到日志信息时或者在请求其他的第三方接口时需要用到实际的用户 IP 地址传入,在本节中会提供服务端在实际获取 IP 地址的源码以及通过 Nginx 代理后 IP 地址隐藏的问题

用途/场景

获取经纬度

无论是小程序还是 App 端,当用户未开启地理位置授权时,在前端页面是无法拿到当前用户所在的经纬度信息的,这时候还有另外一种途径来获取经纬度,那就是通过 IP 地址来解析用户真实请求时所在的经纬度

在一般情况下,都是由前端来拿到这块请求的 IP,可能由于某些 API 或版本的限制,导致前端在所获取的 IP 地址不准确,此时,不得不让后端的大佬 CASE 出手了

支付接口

在这里插入图片描述

微信 > 小程序支付文档中,终端IP:spbill_create_ip 参数是必填项,虽然在微信那一侧不会去校验这块的 IP 地址是否准确,但真实的 IP 地址有利用我们去排查线上问题,比如 IP 地址都是 127.0.0.1 这样的,你永远都分辨不出到底请求是从那一块服务进来的

白名单配置

当请求第三方接口 API 时,若我们所请求的 IP 地址未配置进白名单时,我们是无法从第三方获取到我们想要得到的信息的,这时候有了前置或后置日志打印我们请求时的 IP,能够更快的帮助我们解决问题

比较友善的第三方 API,在我们请求接口出现白名单的问题,会将我们的 IP 进行返回提示 “该 IP:Xxx,未配置白名单,请联系管理员!”,这时直接拿到返回的错误信息内容进行配置即可,无须任何的日志输入

但是有的第三方 API 就比较鸡肋,只是返回一段 "请求 IP 未配置白名单,请联系管理员!”,这时候如果不+日志打印,那中间去找部署服务的 IP 花费的时间就比这日志打印的时间多了个去

实现源码

请求工具类

/**
 * @author vnjohn
 * @since 2023/10/30
 */
public class IPv4Util {

    private static final String HEADER_FORWARDED_FOR = "x-forwarded-for";
    private static final String HEADER_PROXY_CLIENT_IP = "Proxy-Client-IP";
    private static final String HEADER_WL_PROXY_CLIENT_IP = "WL-Proxy-Client-IP";
    private static final String HEADER_HTTP_CLIENT_IP = "http_client_ip";
    private static final String HEADER_HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR";

    private static final String UNKNOWN = "unknown";
    private static final String CHAR_COLON = ":";
    private static final String CHAR_COMMA = ",";

    public static String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader(HEADER_FORWARDED_FOR);
        boolean ipIsEmpty = ip == null || ip.length() == 0;
        if (ipIsEmpty || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader(HEADER_PROXY_CLIENT_IP);
        }
        if (ipIsEmpty || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader(HEADER_WL_PROXY_CLIENT_IP);
        }
        if (ipIsEmpty || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if (ipIsEmpty || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader(HEADER_HTTP_CLIENT_IP);
        }
        if (ipIsEmpty || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader(HEADER_HTTP_X_FORWARDED_FOR);
        }
        // 如果是多级代理,那么取第一个ip为客户ip
        if (ip != null && ip.contains(CHAR_COMMA)) {
            ip = ip.substring(ip.lastIndexOf(CHAR_COMMA) + 1, ip.length()).trim();
        }
        //判断IP是否存在带有端口号的情况、应该要去掉端口号
        if (ip != null && ip.contains(CHAR_COLON)) {
            ip = ip.substring(0, ip.indexOf(CHAR_COLON));
        }
        return ip;
    }

    /**
     * 获取请求的ip
     */
    public static String getRequestIp() {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        // 从获取 RequestAttributes 中获取 HttpServletRequest 信息
        HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
        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("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    public static void main(String[] args) {
        System.out.println(getRequestIp());
    }
}

在其他地方,需要获取 IP 时,只需要按如下传入参数:

HttpServletRequest request

如下调用即可:

IPv4Util.getClientIp(request);

Nginx 代理配置

在 server 标签模块中指定的请求前缀配置一个 location 或直接在 server 标签内进行配置,如下:

location /app {
       proxy_set_header Host $host;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_pass http://localhost:8084;
}

只有当设置了 proxy_set_header X-Real-IP 代理参数以后,获取服务请求的 IP 才是准确的

小结

注意:只有在 Nginx 代理配置以下内容以后,通过请求工具类才能获取到真实的 IP 地址!!!

总结

该篇博文主要介绍的是如何在服务端中获取用户请求的真实 IP 地址,通过几种用途/场景介绍其所在的必要性:获取经纬度、支付接口、白名单配置,当然,为了让你能够快速的运用起来,提供了请求工具类的源码以及告知你如何在 Nginx 进行代理配置,希望这篇短文能够帮助到您,解决您实际工作中的一些问题,期待三连支持🌹

🌟🌟🌟愿你我都能够在寒冬中相互取暖,互相成长,只有不断积累、沉淀自己,后面有机会自然能破冰而行!

博文放在 业务设计 专栏里,欢迎订阅,会持续更新!

如果觉得博文不错,关注我 vnjohn,后续会有更多实战、源码、架构干货分享!

推荐专栏:Spring、MySQL,订阅一波不再迷路

大家的「关注❤️ + 点赞👍 + 收藏⭐」就是我创作的最大动力!谢谢大家的支持,我们下文见!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1150276.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

跑腿小程序开发解析:技术架构、接口设计和前沿趋势

随着生活节奏的加快和个人需求的增加,跑腿小程序成为了人们生活中不可或缺的一部分。从技术角度来看,一个高效、安全、以及用户友好的跑腿小程序是由多个关键要素构成的,包括技术架构、接口设计和前沿趋势。 技术架构 1. 前端技术选型 选择…

Windows Server 2016磁盘管理使用指南:看完即会!

如何打开Windows Server 2016磁盘管理器? 磁盘管理首先在Windows XP中引入,是一个Windows内置实用程序,可让你管理硬盘和关联的分区或卷。在Windows Server磁盘管理对硬盘进行分区非常方便。你可以通过以下方法之一访问它: 方…

数据库系统原理与实践 笔记 #6

文章目录 数据库系统原理与实践 笔记 #6数据库设计和E-R模型设计过程实体-联系模型实体集联系集联系集中实体的角色联系集的度属性复合属性 约束映射基数约束参与约束实体集的码联系集的码冗余属性 实体-联系图E-R图参与联系集中的实体集基数约束角色三元关系上的基数约束弱实体…

JMeter简单使用

JMeter是一个功能强大的开源性能测试工具,用于对各种应用程序、协议和服务器进行性能和负载测试。它被广泛用于测试Web应用程序的性能,并可以模拟多种负载条件和行为。 JMeter使用 添加线程组 设置线程组的配置 设置请求 配置请求 添加监听器 查看压…

Java微服务构建:打造健壮订单模型的完整指南

Java微服务构建一个健壮的订单模型(业务,规划,设计与实现) 在设计领域业务模型时,我们通常会追求理论完美,而忽略实践的脆弱性。尽管我们没有贬低领域建模的意图,但事实上,在电商技术发展多年之后,某些系统…

idea中启动多例项目配置

多实例启动 日常本地开发微服务项目时,博主想要验证一下网关的负载均衡以及感知服务上下线能力时,需要用到多实例启动。 那么什么是多实例启动嘞?简单说就是能在本地同时启动多个同一服务。打个比方项目中有一个 MobileApplication 服务&…

怎么压缩视频?试试这个方法

怎么压缩视频?我们都知道视频的内存比其他类型的文件都要大很多。那是因为视频的分辨率越高,所包含的像素点就越多,因此文件大小也就越大。而且一般来说,视频文件的时长都比较长,当视频的时间越长,那么视频…

RFID银行款箱智能管理应用解决方案

一、行业背景 随着金融业务的不断发展,金融物流的安全性成为越来越重要的问题,银行金库每天都有大量现金款箱的出入库和配送,如果无法确保及时准确地进行入库、库存控制和出库,将给银行带来巨大的风险,增加了银行的管…

堆栈与队列算法-八皇后问题的求解算法

目录 堆栈与队列算法-八皇后问题的求解算法 C代码 堆栈与队列算法-八皇后问题的求解算法 八皇后问题是一种常见的堆栈应用实例。在国际象棋中的皇后可以在没有限定一步走几格的前提下,对棋盘中的其他棋子直吃、横吃和对角斜吃(左斜吃或右斜吃均可&…

博客模板博客模板

xservices-bpm-6.2.1.1.jar 本人详解 作者:王文峰,参加过 CSDN 2020年度博客之星,《Java王大师王天师》作者 公众号:山峯草堂,非技术多篇文章,专注于天道酬勤的 Java 开发问题、中国国学、传统文化和代码爱…

使用Objective-C和ASIHTTPRequest库进行Douban电影分析

概述 Douban是一个提供图书、音乐、电影等文化内容的社交网站,它的电影频道包含了大量的电影信息和用户评价。本文将介绍如何使用Objective-C语言和ASIHTTPRequest库进行Douban电影分析,包括如何获取电影数据、如何解析JSON格式的数据、如何使用代理IP技…

文心一言 VS 讯飞星火 VS chatgpt (124)-- 算法导论10.5 5题

五、用go语言,给定一个n结点的二叉树,写出一个 O(n)时间的非递归过程,将该树每个结点的关键字输出。要求除该树本身的存储空间外只能使用固定量的额外存储空间,且在过程中不得修改该树,即使是暂时的修改也不允许。 文…

ice和Dtls 传输的创建及1个简单的SFU转发实例

ice和Dtls 传输的创建及1个简单的SFU转发实例 licode中,webrtcconn基于dtlstransport 收发,而dtlstransport通过libnice作为底层。dtlstransport 使用了srtp加解密。文末给出一个简化的sfu实例的实现。对应的,看下M98的代码,更能理解为啥这么做: IceTransportInternal 与D…

Transformer模型原理

NLP预训练模型的架构大致可以分为三类: 1. Encoder-Decoder架构(T5),seq2seq模型,RNN、LSTM网络 2. BERT:自编码语言模型,预测文本随机掩码 3. GPT: 自回归语言模型,预测…

Elasticsearch(一)---搭建

搭建es 不允许root用于运行 创建esuser用户: useradd esuser 设置密码 passwd esuser 让esuser拥有sudo的权限,需要修改/etc/sudoers文件 需要先给/etc/sudoers添加写的权限 [rootnode1 ~]# vim /etc/sudoers 改完之后将写权限删除 三台服务器上操…

“阿里巴巴按关键字搜索接口:一键获取海量商品信息,助力商家抢占市场先机!“

阿里巴巴按关键字搜索商品的接口是通过开放平台提供的API接口来实现的。要使用这个接口,需要进行以下步骤: 确认API接口的请求地址和所需参数:需要先查看API文档,了解所要访问的API接口的请求地址和请求参数,以便正确…

python随手小练13

题目1: 定义学员信息类,包含姓名、成绩属性,定义成绩打印方法 (90分及以上显示优秀,80分及以上显示良好,70分及以上显示中等,60分及以上显示合格,60分以下显示不及格) 具体操作: cl…

基于pyqt5和yolov8的智慧工地施工人工安全检测系统

基于pyqt5和yolov8的智慧工地施工人工安全检测系统 主要基于两者进行集成 在前面模型训练基础上,实现安全马甲、安全面具和安全帽的检测。 核心检测代码 def run(self):self.hilo_corriendo Truemodel YOLO("best.pt")cap cv2.VideoCapture(0)while…

安全生产管理系统助力企业安全细化管理

安全生产管理系统利用完整的安全生产管理体系,结合信息化、数字化和智能化等技术手段,将安全生产过程中的各个环节进行有效整合,使安全管理更加科学、规范和高效。 安全生产管理系统可以对企业安全生产进行全面、细致的管理。它能够实现对企…

NFTScan | 10.23~10.29 NFT 市场热点汇总

欢迎来到由 NFT 基础设施 NFTScan 出品的 NFT 生态热点事件每周汇总。 周期:2023.10.23~ 2023.10.29 NFT Hot News 01/ sudoswap 推出 NFT 做空协议 sudoshort 10 月 24 日,NFT 交易协议 sudoswap 推出 NFT 做空协议 sudoshort,是建立在 su…