TOP

简单实现的flask 带限频的apikey签发续签的demo

pip install flask flask-limiter
import time

from flask import Flask, request, jsonify
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
from functools import wraps

app = Flask(__name__)

limiter = Limiter(
    app=app,
    key_func=get_remote_address,
    default_limits=["100 per day", "10 per hour"]  # 全局默认限频规则
)

# 模拟存储token, 真的用的话用mysql存储然后关系字段自己随便设计吧, 这里仅仅用一个用户名和过期, 这里用户名是为了标示一下信息, 万一有人泄露了方便查, 或者禁用
VALID_API_KEYS = {
    "token名字用对称加密进行生成一串随机字符": ["比如这里放用户名", "这放这token的过期时间戳"],
    # 比如如下的模拟数据
    "db27ca0ff08ce7519bbc45dd93ef2e4c488a279d55d7dd2612b7edd11586264e5f75f279b227c8819f8e409079ca4b89":
        ["羊驼", time.time() + 3600],
}


def require_apikey(view_func):
    """验证token的自定义装饰器"""

    @wraps(view_func)
    def decorated_function(*args, **kwargs):
        # 从请求头中获取APIKey
        token = request.headers.get('X-API-KEY')
        if token and token in VALID_API_KEYS and time.time() < VALID_API_KEYS[token][1]:
            return view_func(*args, **kwargs)
        else:
            return jsonify({"error": "老兄你凭证呢?!"}), 401
    return decorated_function


# 创建token
@app.route('/create_token')
def create_token():
    global VALID_API_KEYS
    # 模拟生成一个token记录, 过期时间为1小时
    token_string = f"token_{time.time()}"
    exp_time = time.time() + 3600
    VALID_API_KEYS[token_string] = ["随便写个名字吧", exp_time]
    return jsonify({"status": "success", "message": "", "data": {
        "token": token_string,
        "exp": exp_time,
    }})


# 续签token
@app.route('/renew_token')
@require_apikey
def renew_token():
    token_string = request.headers.get('X-API-KEY')

    global VALID_API_KEYS
    exp_time = time.time() + 3600
    if VALID_API_KEYS.get(token_string):
        VALID_API_KEYS[token_string][1] = exp_time  # 更细时间为往后一小时
    return jsonify({"status": "success", "message": "", "data": {
        "token": token_string,
        "exp": exp_time,
    }})


@app.route('/by_5_per_minute')
@limiter.limit("5 per minute")  # 对此端点单独设置限频:每分钟5次
@require_apikey  # 需要有效的APIKey
def protected_route():
    return jsonify({"status": "success", "message": "", "data": "hello~~~(by_5_per_minute)"})


@app.route('/hello')
def unprotected_route():
    return jsonify({"status": "success", "message": "", "data": "hello~~~"})


@app.route('/by_1_per_second')
@require_apikey
@limiter.limit("1 per second")  # 非常严格的限频:每秒1次
def status_check():
    return jsonify({"status": "success", "message": "", "data": "hello~~~(by_1_per_second)"})


if __name__ == '__main__':
    app.run(debug=True)

 

posted @ 2025-09-01 18:38  羊驼之歌  阅读(14)  评论(0)    收藏  举报