Col*_*Wal 4 python api-design flask
我正在努力使用flask和flask_limiter构建一个API端点,但我遇到了一个问题。我的目标是在单个端点上对客户端 IP 地址以及客户端提供的 API 密钥(可通过 Flask 的“请求”模块访问)进行速率限制。
IP 地址限制器很重要,因为我想防止暴力攻击,而 API 密钥限制器只是出于商业原因。我已经构建了两个速率限制器,并且它们独立工作(即我可以限制 IP 地址或提供的 API 密钥),但我无法同时在端点上运行这两个速率限制器。到目前为止我尝试过的一个例子:
from flask import Flask, request
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
app = Flask(__name__)
ip_limiter = Limiter(app, key_func=get_remote_address)
get_api_key = lambda : request.args.get('apikey')
api_key_limiter = Limiter(app, key_func=get_api_key)
@app.route('/theEndpoint')
@ip_limiter.limit('some_limit_here')
@api_key_limiter.limit('other_limit_here')
def theEndpointFunction(...):
.......
Run Code Online (Sandbox Code Playgroud)
最好在单个包(即flask_limiter)中实现所有速率限制,但到目前为止,我认为对多个键实现速率限制的唯一方法是切换到redis之类的东西。
关于使用 Flask_limiter 实现多键速率限制的方法有什么线索吗?
如果有人感兴趣,我决定切换到 Redis 来实现我的双密钥速率限制。解决方案是这样的:
class RateLimit(object):
def __init__(self, key, max_requests, seconds):
self.reset = int(time.time()) + seconds
self.key = key
self.max_requests = max_requests
self.seconds = seconds
p = redis.pipeline()
p.incr(self.key)
p.expireat(self.key, self.reset)
self.current = min(p.execute()[0], max_requests)
remaining = property(lambda x: x.max_requests - x.current)
over_limit = property(lambda x: x.current >= x.max_requests)
def get_view_rate_limit():
return getattr(g, '_view_rate_limit', None)
def over_limit(limit):
#formatting a JSON response
response = {"result": "Max number of requests exceeded",
"status": False}
response = jsonify(response)
response.status_code = 400
return response
def ratelimit(max_requests, seconds, key_func, over_limit=over_limit):
def decorator(f):
def rate_limited(*args, **kwargs):
key = key_func()
rlimit = RateLimit(key, max_requests, seconds)
g._view_rate_limit = rlimit
if over_limit is not None and rlimit.over_limit:
return over_limit(rlimit)
return f(*args, **kwargs)
return update_wrapper(rate_limited, f)
return decorator
RATE_LIMIT_FUNCS = {'apikey': lambda: request.args.get('apikey'),
'ip': lambda: get_remote_address}
Run Code Online (Sandbox Code Playgroud)
然后装饰烧瓶端点:
@app.route('/theEndpoint')
@ratelimit(max_requests=5, seconds=300, key_func=RATE_LIMIT_FUNCS['apikey'])
@ratelimit(max_requests=15, seconds=300, key_func=RATE_LIMIT_FUNCS['ip'])
def theEndpointFunction():
....
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3343 次 |
| 最近记录: |