当前位置: 首页 > news >正文

使用 Flask-Limiter 和 Nginx 实现接口访问次数限制

在现代 Web 应用中,针对敏感接口(如短信验证码、登录接口等)的访问次数限制至关重要。通过设置合理的限流策略,可以有效防止接口滥用,避免过多的资源消耗,并提升安全性。本文将通过 Nginx 和 Flask-Limiter 为 Flask 应用实现 IP 级别的限流,同时确保限流基于客户端的真实 IP 地址,而非内网地址如 172.17.0.1

1. 使用 Nginx 作为反向代理

Nginx 通常作为 Web 应用的反向代理,接收来自客户端的请求并将其转发到后端的应用程序(如 Flask)。由于 Nginx 在中间充当代理角色,后端应用获取到的可能是 Nginx 或 Docker 容器的内网 IP(如 172.17.0.1),因此获取客户端真实 IP 就显得非常重要。

Nginx 配置中的关键参数

我们可以通过一些配置,将客户端的真实 IP 地址传递给 Flask 应用:

# 重定向 HTTP 到 HTTPS
server {listen 80;server_name example.com;return 301 https://$host$request_uri;
}# 处理 HTTPS 请求
server {listen 443 ssl http2;server_name example.com;# SSL 证书配置ssl_certificate    /path/to/your/fullchain.pem;ssl_certificate_key    /path/to/your/privkey.pem;ssl_protocols TLSv1.2 TLSv1.3;ssl_ciphers EECDH+AESGCM:EECDH+CHACHA20:!aNULL:!MD5:!DSS;ssl_prefer_server_ciphers on;ssl_session_cache shared:SSL:10m;ssl_session_timeout 10m;add_header Strict-Transport-Security "max-age=31536000" always;# 反向代理到 Flask 应用的 5100 端口location / {proxy_pass http://127.0.0.1:5100;  # 将请求转发到 Flaskproxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}# 日志配置(可选)access_log  /path/to/log/access.log;error_log  /path/to/log/error.log;
}
主要参数解释
  • proxy_pass: 将请求转发到后端的 Flask 应用,通常监听在 127.0.0.1:5100 端口。
  • proxy_set_header Host $host: 将客户端请求的主机名传递给后端应用。
  • proxy_set_header X-Real-IP $remote_addr: 传递客户端的真实 IP 地址给后端应用。$remote_addr 是直接连接到 Nginx 的客户端 IP,通常是原始客户端的 IP。
  • proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for: 将经过的代理链(包括客户端真实 IP)传递给后端应用。这个头通常包含客户端的真实 IP 地址。
  • proxy_set_header X-Forwarded-Proto $scheme: 传递请求使用的协议(HTTP 或 HTTPS)给后端应用。
避免内网 IP 地址 172.17.0.1

如果您的 Flask 应用运行在 Docker 容器中,而 Nginx 也运行在同一服务器上,后端 Flask 应用接收到的 IP 可能是 172.17.0.1,这是 Docker 内网的默认网关地址。这个地址会导致所有请求都被认为来自同一个 IP,从而错误地进行限流。

通过上述 Nginx 配置中的 X-Forwarded-For 头部,我们可以将客户端的真实 IP 地址传递给 Flask,避免使用 Docker 内部的 IP(如 172.17.0.1)进行限流。

2. 使用 Flask-Limiter 实现限流

Flask-Limiter 是一个非常方便的库,用于限制 Web 应用中的接口访问次数。我们可以结合 Nginx 的配置,通过 X-Forwarded-For 获取到真实的客户端 IP,基于 IP 实现限流。

安装 Flask-Limiter

首先,确保 Flask-Limiter 已安装:

pip install flask-limiter

 基于 IP 地址限流的 Flask 代码

from flask import Flask, request, jsonify
from flask_limiter import Limiterapp = Flask(__name__)# 获取真实客户端 IP 地址
def get_client_ip():# 检查是否有 X-Forwarded-For 头部if request.headers.getlist("X-Forwarded-For"):return request.headers.getlist("X-Forwarded-For")[0]  # 获取真实的客户端 IPelse:return request.remote_addr  # 使用默认的 remote_addr# 初始化 Flask-Limiter,并使用 get_client_ip 作为限流的 key_func
limiter = Limiter(key_func=get_client_ip,  # 使用真实的客户端 IP 进行限流app=app,storage_uri="redis://<your_redis_host>:<redis_port>/1"  # 使用 Redis 存储限流信息
)# 定义接口,并为每个 IP 地址限制每分钟 1 次,每天最多 15 次访问
@app.route('/send_verification_code', methods=['POST'])
@limiter.limit("1 per minute; 15 per day")
def send_verification_code():phone_number = request.form.get('phone_number')machine_id = request.headers.get('Machine-Id')if not phone_number:return jsonify({"error": "手机号不能为空"}), 400if not machine_id:return jsonify({"error": "Machine-Id 不能为空"}), 400# 处理发送验证码的逻辑return jsonify({"message": "验证码发送成功"}), 200if __name__ == '__main__':app.run(debug=True)
代码解释
  1. get_client_ip 函数: 用于获取真实的客户端 IP,优先使用 X-Forwarded-For 头部中的第一个 IP 地址(通常为客户端 IP),如果没有,则使用 request.remote_addr

  2. Flask-Limiter 配置: key_func 设置为 get_client_ip,确保限流基于客户端的真实 IP。storage_uri 指定 Redis 存储限流信息,避免 Flask 重启或进程切换时丢失限流数据。

  3. @limiter.limit("1 per minute; 15 per day"): 设置限流规则,限制每个 IP 每分钟只能请求一次,每天最多 15 次。

3. Redis 存储限流信息

Flask-Limiter 支持使用 Redis 存储限流信息,这样即使 Flask 应用重启,限流信息也不会丢失。通过 Redis 可以实现跨进程的限流。

Redis 连接配置
limiter = Limiter(key_func=get_client_ip,app=app,storage_uri="redis://:password@redis_host:6379/1"  # 使用 Redis db1
)

4. 验证限流

通过上述配置,当 Flask-Limiter 生效时,Redis 中的键将会包含真实的客户端 IP,并记录请求的访问次数。例如,Redis 中的键可能类似于:

LIMITS:LIMITER/<client_real_ip>/send_verification_code/1/1/minute

这样,限流规则是基于客户端真实 IP 地址的,避免了因 Docker 内网 IP 172.17.0.1 导致的限流错误。

5. 总结

通过 Nginx 的反向代理配置,我们可以将客户端的真实 IP 传递给 Flask 应用。结合 Flask-Limiter,可以基于客户端的真实 IP 地址,实现针对敏感接口的访问频率限制。这样不仅可以提升 Web 应用的安全性,还能有效防止滥用行为。

核心步骤总结如下:

  • Nginx 配置: 使用 X-Forwarded-ForX-Real-IP 头部传递客户端 IP,避免使用 172.17.0.1 等内网 IP。
  • Flask-Limiter: 结合 Redis 实现基于 IP 地址的访问次数限制。
  • 客户端真实 IP 获取: 通过 get_client_ip 函数确保 Flask 获取到真实的客户端 IP。

这种限流机制为 Web 应用的安全和性能提供了重要保障。

相关文章:

使用 Flask-Limiter 和 Nginx 实现接口访问次数限制

在现代 Web 应用中&#xff0c;针对敏感接口&#xff08;如短信验证码、登录接口等&#xff09;的访问次数限制至关重要。通过设置合理的限流策略&#xff0c;可以有效防止接口滥用&#xff0c;避免过多的资源消耗&#xff0c;并提升安全性。本文将通过 Nginx 和 Flask-Limiter…...

【数据结构】排序算法---冒泡排序

文章目录 1. 定义2. 算法步骤3. 动图演示4. 性质5. 算法分析6. 代码实现C语言PythonJavaCGo 结语 1. 定义 冒泡排序&#xff08;英语&#xff1a;Bubble sort&#xff09;是一种简单的排序算法。它重复地走访过要排序的数列&#xff0c;一次比较两个元素&#xff0c;如果它们的…...

mysql数据库中事务锁的机制

读锁又称为共享锁&#xff0c;简称S锁&#xff0c;共享锁就是多个事务对于同一数据可以共享一把锁&#xff0c;都能访问到数据&#xff0c;但是只能读不能修改。 写锁又称为排他锁&#xff0c;简称X锁&#xff0c;排他锁就是不能与其他所并存&#xff0c;如一个事务获取了一个…...

并发工具类-CountDownLatch

CountDownLatch 是 Java 中提供的一种非常有用的并发工具类&#xff0c;位于 java.util.concurrent 包中。它可以使一个或多个线程等待其他线程完成一组特定的操作后再继续执行。CountDownLatch 通过维护一个计数器来实现这一点&#xff0c;计数器的初始值由构造函数设定。每当…...

进程的重要函数

进程的重要函数: fork函数 了解fork函数 通过调用fork()函数&#xff0c;则会产生一个新的进程。调用fork()函数的进程叫做 父进程&#xff0c;产生的新进程则为子进程。 其编码过程: 1.函数功能: 函数头文件 #include <sys/types.h> #include <unistd.h> 函数…...

python 实现average median平均中位数算法

average median平均中位数算法介绍 平均&#xff08;Mean&#xff09;和中位数&#xff08;Median&#xff09;是统计学中常用的两个概念&#xff0c;用于描述一组数据的中心趋势&#xff0c;但它们并不是算法&#xff0c;而是数据处理的结果。不过&#xff0c;我可以解释如何…...

HTML概述

1. HTML概述 1.1 HTML定义 HTML超文本标记语言&#xff0c;其中超文本是链接&#xff0c;标记也叫标签&#xff08;即带尖括号的文本&#xff09;。 1.2 HTML基本骨架 HTML基本骨架是网页模板。 <html><head><title>网页的标题</title></head&…...

【FFT】信号处理——快速傅里叶变换【通俗易懂】

快速傅里叶变换&#xff08;Fast Fourier Transform, FFT&#xff09;是一种用于将信号从时间域转换到频率域的算法。 傅里叶变换的核心思想是&#xff1a;任何周期性信号都可以分解成多个不同频率的正弦波或余弦波的叠加。 简单来说&#xff0c;FFT可以帮助我们理解一个信号…...

电脑升级WIN11之后需要注意哪些东西

1.记事本&#xff0c;在前单位时&#xff0c;电脑升级后&#xff0c;记事本会需要手动更新&#xff0c;或手动安装 2.任务栏&#xff0c;WIN11默认任务栏在中间位置&#xff0c;想要调成WIN10一样的位置&#xff0c;分享两个方法 拖拽法&#xff08;适用于Windows 11 2022年1…...

GEE 教程:利用sentinel-5p数据进行长时序CO一氧化碳的监测分析并结合夜间灯光数据分析

目录 简介 数据 哨兵5号 NOAA/VIIRS/DNB/MONTHLY_V1/VCMCF 函数 ui.Chart.image.series(imageCollection, region, reducer, scale, xProperty) Arguments: Returns: ui.Chart 代码 结果 简介 利用sentinel-5p数据进行长时序CO一氧化碳的监测分析并结合夜间灯光数据…...

【教程】鸿蒙ARKTS 打造数据驾驶舱---前序

鸿蒙ARKTS 打造数据驾驶舱 ​ 前面2章我介绍了如何通过定义View绘制箭头以及圆形进度&#xff0c;初步了解了鸿蒙如何进行自定义View。接下来我将通过我最近在带的一个VUE的项目&#xff0c;简单实现了几个鸿蒙原生页面。帮助大家快速上手纯血鸿蒙开发. 本项目基于Api11Stage模…...

Html css样式总结

1.Html css样式总结 CSS 定义 中文名称&#xff1a;层叠样式表 。 英文全称&#xff1a;Cascading Style Sheets &#xff0c;简称CSS。在网页制作时采用CSS技术&#xff0c;可以有效地对页面的布局、字体、颜色、背景和其它效果实现更加精确的控制。 &#xff08;1&#xff09…...

决策树基础概论

1. 概述 在机器学习领域&#xff0c;决策树&#xff08;Decision Tree&#xff09; 是一种高度直观且广泛应用的算法。它通过一系列简单的是/否问题&#xff0c;将复杂的决策过程分解为一棵树状结构&#xff0c;使得分类或回归问题的解决过程直观明了。决策树的最大特点在于可…...

Spring Boot集成Akka Cluster快速入门Demo

1.什么是Akka Cluster&#xff1f; Akka Cluster将多个JVM连接整合在一起&#xff0c;实现消息地址的透明化和统一化使用管理&#xff0c;集成一体化的消息驱动系统。最终目的是将一个大型程序分割成若干子程序&#xff0c;部署到很多JVM上去实现程序的分布式并行运算&#xf…...

django学习入门系列之第十点《A 案例: 员工管理系统10》

文章目录 12 管理员操作12.4 密码加密12.5 获取对象&#xff08;防止id错误--编辑界面等&#xff09;12.6 编辑管理员12.7 重置密码 往期回顾 12 管理员操作 12.4 密码加密 密码不应该以明文的方式直接存储到数据库&#xff0c;应该加密才放进去 定义一个md5的方法&#xff…...

Unity实战案例全解析:PVZ 植物卡片状态分析

Siki学院2023的PVZ免费了&#xff0c;学一下也坏 卡片状态 卡片可以有三种状态&#xff1a; 1.阳光足够&#xff0c;&#xff08;且cd好了可以种植&#xff09; 2.阳光不够&#xff0c;&#xff08;cd&#xff1f;好了&#xff1a;没好 &#xff08;三目运算符&#xff09;&…...

判断变量是否为有限数字(非无穷大或NaN)math.isfinite() 判断变量是否为无穷大(正无穷大或负无穷大)math.isinf()

【小白从小学Python、C、Java】 【考研初试复试毕业设计】 【Python基础AI数据分析】 判断变量是否为有限数字&#xff08;非无穷大或NaN&#xff09; math.isfinite() 判断变量是否为无穷大&#xff08;正无穷大或负无穷大&#xff09; math.isinf() 请问关于以下代码表述错误…...

idea使用阿里云服务器运行jar包

说明&#xff1a;因为我用的阿里云服务器不是自己的&#xff0c;所以一些具体的操作可能不太全面。看到一个很完整的教程&#xff0c;供参考。 0. 打包项目 这里使用的是maven打包。 在pom.xml中添加以下模块。 <build><plugins><plugin><groupId>org…...

解决nginx代理SSE接口的响应没有流式返回

目录 现象原来的nginx配置解决 现象 前后端分离的项目&#xff0c;前端访问被nginx反向代理的后端SSE接口&#xff0c;预期是流式返回&#xff0c;但经常是很久不响应&#xff0c;一响应全部结果一下子都返回了。查看后端项目的日志&#xff0c;响应其实是流式产生的。推测是n…...

11 - TCPClient实验

在上一个章节的UDP通信测试中&#xff0c;尽管通信的实现过程相对简洁&#xff0c;但出现了通信数据丢包的问题。因此&#xff0c;本章节将基于之前建立的WIFI网络连接&#xff0c;构建一个基础的TCPClient连接机制。我们利用网络调试助手工具来发送数据&#xff0c;测试网络通…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

C++.OpenGL (20/64)混合(Blending)

混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...

C++ 设计模式 《小明的奶茶加料风波》

&#x1f468;‍&#x1f393; 模式名称&#xff1a;装饰器模式&#xff08;Decorator Pattern&#xff09; &#x1f466; 小明最近上线了校园奶茶配送功能&#xff0c;业务火爆&#xff0c;大家都在加料&#xff1a; 有的同学要加波霸 &#x1f7e4;&#xff0c;有的要加椰果…...

C# 表达式和运算符(求值顺序)

求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如&#xff0c;已知表达式3*52&#xff0c;依照子表达式的求值顺序&#xff0c;有两种可能的结果&#xff0c;如图9-3所示。 如果乘法先执行&#xff0c;结果是17。如果5…...

在树莓派上添加音频输入设备的几种方法

在树莓派上添加音频输入设备可以通过以下步骤完成&#xff0c;具体方法取决于设备类型&#xff08;如USB麦克风、3.5mm接口麦克风或HDMI音频输入&#xff09;。以下是详细指南&#xff1a; 1. 连接音频输入设备 USB麦克风/声卡&#xff1a;直接插入树莓派的USB接口。3.5mm麦克…...

【WebSocket】SpringBoot项目中使用WebSocket

1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖&#xff0c;添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...

java高级——高阶函数、如何定义一个函数式接口类似stream流的filter

java高级——高阶函数、stream流 前情提要文章介绍一、函数伊始1.1 合格的函数1.2 有形的函数2. 函数对象2.1 函数对象——行为参数化2.2 函数对象——延迟执行 二、 函数编程语法1. 函数对象表现形式1.1 Lambda表达式1.2 方法引用&#xff08;Math::max&#xff09; 2 函数接口…...