我正在构建一个 Flask Web 应用程序,并且我正在尝试返回自定义错误消息,以防 auth 标头丢失时引发的 401 错误。对于身份验证,我使用 Flask-Jwt-Extended。我想覆盖
expired_token_loader(callback)
以返回 401 错误,然后使用 @app.errohandler(401) 捕获它并重定向到登录。@jwt.unauthorized_loader
def unauthorized_callback(callback):
# Missing auth header
# abort(401)
return make_response("", 401)
@app.errorhandler(401)
def unauthorized(e):
return "Custom 401 Error", 401
在Flask-JWT-Extended官方文档中发现用@jwt.unauthorized_loader修饰的函数必须返回Flask Response。
因此,当我尝试如上所示
abort(401)
并且不从 unaturhorized_callback()
返回任何内容时,它会显示 werkzeug.exceptions.Unauthorized: 401 Unauthorized: ...
return make_response("", 401)
它显示这一点时,这意味着错误处理程序没有处理错误:@jwt.unauthorized_loader
内重定向时,它始终是错误302,否则重定向将不起作用。所以我不能做make_response(redirect("/login"), 401)
。 所以我的目标是抛出 401 错误,然后在 Web 应用程序和移动应用程序中以不同的方式处理它。谢谢你的帮助。
我相信这不起作用的原因是因为
@jwt.unauthorized_loader
的回调方法已经在@app.errorhandler
的上下文中调用,并且错误处理程序中引发的任何异常都不会导致触发其他错误处理程序。
与其尝试通过中止和异常控制流来处理此问题,为什么不直接使用辅助方法来进行自定义响应并在两个地方使用它?
def unauthorized_response():
return make_response("Custom 401 Error", 401)
@jwt.unauthorized_loader
def unauthorized_callback(callback):
return unauthorized_response()
@app.errorhandler(401)
def unauthorized(e):
return unauthorized_response()
不完全是我想要的,但最终它满足了我的需要。使用自定义 http 响应代码进行重定向,我使用 401 代码进行了
render_template
,如下所示:@jwt.unauthorized_loader
def unauthorized_callback(callback):
# Missing auth header
flash("Missing auth header please login")
return make_response(render_template("login.html"), 401)
如果您使用flask_restful,则可以在初始化API时定义错误字典以映射特定异常:
from flask import Flask
from flask_restful import Api
from flask_jwt_extended import JWTManager
from flask_jwt_extended.exceptions import NoAuthorizationError
from jwt.exceptions import ExpiredSignatureError
app = Flask(__name__)
api = Api(app, errors={
'NoAuthorizationError': {
'message': "Missing Authorization Header",
'status': 401,
},
'ExpiredSignatureError': {
'message': "Token has expired",
'status': 401,
},
})
jwt = JWTManager(app)
# Continue setting up routes and jwt protected endpoints