【问题标题】:Flask-Limiter does not work with Flask-Restful API-based applicationFlask-Limiter 不适用于基于 Flask-Restful API 的应用程序
【发布时间】:2020-06-07 16:21:19
【问题描述】:

我正在尝试使用flask_restfulflask_jwt_extendedflask_limiter 构建一个 RESTful API 应用程序,以将用户的配额限制为 6/分钟。我的玩具/测试代码如下(尚未实现实际的授权方案):

from flask import Flask, make_response
from flask_restful import Api, Resource
from flask_limiter import Limiter
from werkzeug.exceptions import HTTPException
from flask_jwt_extended import jwt_required, create_access_token, JWTManager, get_jwt_identity

# custom HTTP exception
class OutOfQuota(HTTPException):
    code = 402
    name = 'Out Of Quota'

app = Flask(__name__)
limiter = Limiter(app, key_func=get_jwt_identity)

api = Api(prefix='')

class Token(Resource):
    def get(self, user):
        return make_response({'token': create_access_token(identity=user)})

class Test(Resource):
    @jwt_required
    @limiter.limit('6/minute')
    def get(self):
        return make_response({'message': f'OK {get_jwt_identity()}'})

api.add_resource(Token, '/token/<string:user>')
api.add_resource(Test, '/test')

api.init_app(app)

# custom error handler (change "Payment Required" to "Out Of Quota" HTTP status
@app.errorhandler(429)
def ratelimit_handler(e):
    return OutOfQuota(f'quota limit exceeded: {e.description}')

jwt = JWTManager(app)

app.config['JWT_SECRET_KEY'] = 'nothing-fancy-for-now'

if __name__ == '__main__':
    app.run(host='localhost', port=8080)

端点/token 为用户生成一个 JWT 令牌,其用户名存储在内部作为 JWT 身份。当使用此令牌访问/test 端点时,我想检查此特定用户(即此特定身份)访问此端点的次数,因此使用get_jwt_identity 作为key_funcLimiter .

问题是我在运行上述代码时访问/test端点时没有任何限制;我可以随心所欲地访问它,尽可能快地访问它。我在这里遗漏了什么吗?

【问题讨论】:

    标签: python python-3.x flask flask-restful flask-jwt-extended


    【解决方案1】:

    我遇到了类似的问题,并找到了一个似乎可行的解决方案。 Flask-Restful 做的事情有点不同。它创建可插入的视图。 Flask-Limiter 文档中有一个关于这个特殊案例的部分 - https://flask-limiter.readthedocs.io/en/stable/#using-flask-pluggable-views

    class Test(Resource):
    
      decorators = [limiter.limit("5/minute")]
    
      def get(self):
         ...
    

    我们需要以这种方式提供,而不是通过@limiter.limit 提供装饰器。

    我还有一个关于从哪里获得limiter 参考的问题。在某个基目录中,您可以实现它并在您的类中导入。

    from flask import Flask
    from flask_limiter import Limiter
    from flask_limiter.util import get_remote_address
    
    _app = Flask(__name__)
    limiter = Limiter(
        _app,
        key_func=get_remote_address
    )
    

    【讨论】:

      猜你喜欢
      • 2021-10-02
      • 1970-01-01
      • 1970-01-01
      • 2015-05-08
      • 2015-11-22
      • 2013-10-16
      • 1970-01-01
      • 2022-06-14
      • 2011-11-22
      相关资源
      最近更新 更多