【问题标题】:Combining Flask Blueprints with Flask-JWT将 Flask 蓝图与 Flask-JWT 相结合
【发布时间】:2017-02-24 04:09:28
【问题描述】:

我正在开发一个带有蓝图的Flask 0.12 应用程序,我正在尝试使用Flask-JWT (0.3.2) 进行身份验证。

我看到的 Flask-JWT 教程都没有使用蓝图。

每个示例中通常都有一段代码,执行如下操作:

app = Flask(__name__)
jwt = JWT(app, authenticate, identity)

在蓝图烧瓶应用程序中,结构往往更像这样:

__init__.py

from swarm.controllers.main import main
from swarm.controllers.grid import grid
from swarm.controllers.address import address

def create_app(object_name):
    app = Flask(__name__)
    ...
    app.register_blueprint(main)
    app.register_blueprint(grid)
    app.register_blueprint(address)

controllers/main.py:

main = Blueprint('main', __name__)

controllers/grid.py:

grid = Blueprint('grid', __name__)

controllers/address.py:

address = Blueprint('address', __name__)

如何引用Flask-JWT 并在控制器中使用它的装饰器?

通过展示如何将 JWT 装饰器添加到标准示例(例如烧瓶源代码中的 blueprintexampleMichał Karzyński's REST API demo),可能会更容易回答这个问题。

【问题讨论】:

  • 蓝图只是让您能够围绕应用程序的概念块组织代码,它实际上与普通的 Flask 应用程序并没有什么不同。您在上面显示的来自main.py, grid.py, address.py 的代码应该放入__init__.py 文件中,以使它们成为正确的python 模块。在您的主 __init__.py 文件中实例化 Flask-JWT,然后从您要使用的蓝图中导入它并装饰这些路由。我通常有一个 auth 蓝图,通过我的身份验证服务(使用 JWT)来管理登录、注销、回调等。
  • 我不太明白为什么每个控制器都需要自己的 controllers/mycontroller/__init__.py 而不仅仅是 controllers/mycontroller.py
  • 我已经尝试过你的方法,我的代码中似乎有循环引用。
  • 例如,用这个 repo 进行了尝试:github.com/postrational/rest_api_demo,它使用这种方法陷入了一堆:app.py: jwt = JWT(app, authenticate, identify)api/grid/endpoints/posts.py: from rest_api_demo.app import jwt
  • 新手注意事项:请改用 Flask-JWT-Extended,它位于 flask-jwt-extended.readthedocs.io/en/stable,最近已更新并有更好的文档。

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


【解决方案1】:

我构建了一个简单的示例,可以使用 Flask-JWT 装饰器。

文件结构:

server
├── app
|   ├── admin # blueprint
|   |   ├── __init__.py
|   |   ├── views.py
|   ├── __init__.py
├── config.py
└── run.py

首先,创建一个名为admin 的蓝图并导入其视图

# file: server/app/admin/init.py
from flask import Blueprint

admin = Blueprint('admin', __name__)

from . import views

admin 蓝图有一个视图。在这里,我们导入 admin 蓝图和一些 flask_jwt 东西,以便我们可以正确访问它们的装饰器:

from flask_jwt import jwt_required, current_identity
from . import admin

# file: server/app/admin/views.py
@admin.route('/protected')
@jwt_required()
def protected():
    return '%s' % current_identity

现在创建flask应用,创建JWT实例,并将admin蓝图注册到flask应用:

# file: server/app/__init__.py
from flask import Flask
from flask_jwt import JWT
from werkzeug.security import safe_str_cmp

from .admin import admin

# skipping over jwt authenticate() and identity() creation
# https://pythonhosted.org/Flask-JWT/
# ...

app = Flask(__name__)

app.config.from_object('config')

jwt = JWT(app, authenticate, identity)

app.register_blueprint(admin, url_prefix='/admin')

最后,设置您的脚本管理器:

from flask_script import Manager, Server

from server.app import app

manager = Manager(app)

# Turn on debugger by default and reloader
manager.add_command("runserver", Server(
    use_debugger = True,
    use_reloader = True,
    host = '0.0.0.0',
    port = 5000)
)

if __name__ == "__main__":
    manager.run()

现在,如果我们访问我们的 /admin/protected url,我们将看到 JWT 已启动并正在运行:

{
  "description": "Request does not contain an access token",
  "error": "Authorization Required",
  "status_code": 401
}

我希望这会有所帮助!

【讨论】:

  • 感谢您提供非常详细和清晰的答案。我首先创建了您的应用程序并使其正常工作,然后在我的应用程序中进行了适当的更改。一切都很好。
  • 我注意到我做错的另一件事是将 @jwt_required 装饰器放在 API 类方法周围,而不是放在类本身周围。这是正确的做法:
  • @jwt_required() @api.route('/api/user/<int:uid>') class User(Resource):
  • @ChrisGuest api.route 必须是最外层的装饰器。见stackoverflow.com/a/31757446/5819113
  • 如何为所有注册的蓝图控制器编写一个通用的撤销令牌方法
猜你喜欢
  • 1970-01-01
  • 2019-02-04
  • 2012-09-14
  • 2020-05-18
  • 1970-01-01
  • 1970-01-01
  • 2017-05-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多