如何在FLASK应用中对无登录认证的单个用户限制API调用次数
问题核心结论
完全不获取任何可区分用户的标识、完全不存储任何用户相关计数数据的前提下,无法实现单用户维度的限流——因为你没有办法判断两个请求来自同一个用户还是不同用户,自然无法按单个用户做额度统计。
但可以实现无需登录认证、不收集可直接识别个人身份的信息、不在业务数据库存储任何用户相关数据的方案,完全匹配你的业务需求。
推荐实现方案
推荐使用 Flask-Limiter 扩展实现,你之前用的默认是全局路由维度限流,只要修改限流标识生成规则即可支持单用户维度限流:
- 无需用户登录认证,用户侧完全无感知
- 计数数据可以存在服务端内存或Redis中,到期自动清理,不需要写入业务数据库
- 仅用请求IP或匿名Cookie作为用户区分标识,不会收集手机号、账号、设备指纹等可直接识别个人身份的信息
方案1:基于IP标识实现(最简便)
单实例部署场景下直接用这个方案即可:
安装扩展
pip install flask-limiter代码示例
from flask import Flask from flask_limiter import Limiter from flask_limiter.util import get_remote_address app = Flask(__name__) # 初始化限流器,以请求IP作为单用户区分标识,计数存在服务端内存 limiter = Limiter( key_func=get_remote_address, app=app, storage_uri="memory://", ) # 给目标路由设置限流规则:单用户单日4次调用额度 @app.route("/your-target-route") @limiter.limit("4/day") def target_route(): # 你的业务逻辑 return "请求成功"
如果是多实例部署,把storage_uri的值换成Redis地址(如redis://127.0.0.1:6379)即可,计数会存在Redis中,自动按规则过期,不需要你手动维护数据。
方案2:基于匿名Cookie实现(准确率更高)
如果存在多个用户共用同一个出口IP的场景,用IP标识容易出现误限流,可以改用匿名Cookie作为用户标识:
from flask import Flask, request, make_response from flask_limiter import Limiter import uuid app = Flask(__name__) # 自定义限流标识生成逻辑,读取用户端存储的匿名Cookie def get_anonymous_user_id(): return request.cookies.get("user_limit_id", None) limiter = Limiter( key_func=get_anonymous_user_id, app=app, storage_uri="memory://", ) @app.route("/your-target-route") @limiter.limit("4/day") def target_route(): resp = make_response("请求成功") # 新用户生成随机匿名标识,存在用户端Cookie,有效期1天 if "user_limit_id" not in request.cookies: resp.set_cookie( "user_limit_id", str(uuid.uuid4()), max_age=86400, httponly=True ) return resp
这个方案的标识完全由随机字符串生成,不会关联任何用户身份信息,且存储在用户端,服务端仅存计数数据,到期自动清理。
内容的提问来源于stack exchange,提问作者Moritz
相关产品推荐
相关产品推荐

