You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在FLASK应用中对无登录认证的单个用户限制API调用次数

问题核心结论

完全不获取任何可区分用户的标识、完全不存储任何用户相关计数数据的前提下,无法实现单用户维度的限流——因为你没有办法判断两个请求来自同一个用户还是不同用户,自然无法按单个用户做额度统计。

但可以实现无需登录认证、不收集可直接识别个人身份的信息、不在业务数据库存储任何用户相关数据的方案,完全匹配你的业务需求。

推荐实现方案

推荐使用 Flask-Limiter 扩展实现,你之前用的默认是全局路由维度限流,只要修改限流标识生成规则即可支持单用户维度限流:

  • 无需用户登录认证,用户侧完全无感知
  • 计数数据可以存在服务端内存或Redis中,到期自动清理,不需要写入业务数据库
  • 仅用请求IP或匿名Cookie作为用户区分标识,不会收集手机号、账号、设备指纹等可直接识别个人身份的信息

方案1:基于IP标识实现(最简便)

单实例部署场景下直接用这个方案即可:

  1. 安装扩展
    pip install flask-limiter

  2. 代码示例

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.20 09:45:10