将Flask蓝图与Flask-JWT相结合

3
我正在使用蓝图开发基于 Flask 0.12 的应用,并尝试使用 Flask-JWT(0.3.2)进行身份验证。
我找不到任何适用于 Flask-JWT 和蓝图的教程。
每个示例通常都有一段代码,类似于以下内容:
app = Flask(__name__)
jwt = JWT(app, authenticate, identity)

在经过蓝图设计的 Flask 应用中,其结构通常更像这样:

__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装饰器添加到标准示例(例如blueprintexample在flask源代码中或Michał Karzyński的REST API演示)可能更容易回答这个问题。


蓝图只是让你将代码组织成应用程序的概念块,它实际上与普通的Flask应用程序没有什么不同。您在main.py、grid.py、address.py中展示的代码应该放入__init__.py文件中,以使它们成为适当的Python模块。在主__init__.py文件中实例化Flask-JWT,然后从要使用的蓝图中导入它并装饰这些路由。我通常有一个__auth__蓝图来管理登录、注销、回调等我的身份验证服务(使用JWT)。 - abigperson
我不太明白为什么每个控制器都需要自己的controllers/mycontroller/init.py文件,而不是只有controllers/mycontroller.py文件。 - ChrisGuest
我尝试了你的方法,但我的代码似乎出现了循环引用。 - ChrisGuest
例如,使用此存储库进行尝试:https://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 - ChrisGuest
新手注意:请使用 Flask-JWT-Extended,它可以在 https://flask-jwt-extended.readthedocs.io/en/stable/ 找到,该库已经更新得更近,并且有更好的文档。 - Alexey Nikonov
1个回答

7

我已经创建了一个简单的示例,使得可以使用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 网址,我们会看到 JWT 已经启动:
{
  "description": "Request does not contain an access token",
  "error": "Authorization Required",
  "status_code": 401
}

我希望这能帮到你!

感谢您提供如此详细和清晰的答案。我首先创建了您的应用程序并使其正常工作,然后将适当的更改应用到我的应用程序中。一切都很好。 - ChrisGuest
我注意到自己犯了一个错误,那就是将@jwt_required装饰器放在API类方法周围而不是类本身周围。以下是正确的做法: - ChrisGuest
1
@jwt_required() @api.route('/api/user/<int:uid>') class User(Resource): - ChrisGuest
@ChrisGuest api.route 必须是最外层的装饰器。请参见 https://stackoverflow.com/a/31757446/5819113。 - bluesmonk
如何为所有已注册的蓝图控制器编写一个通用的撤销令牌方法。 - Ashok Sri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接