首页 > 解决方案 > 如何将授权标头添加到请求中,以便在标头上存在访问令牌时可以访问带有 @jwt_required 的烧瓶路由

问题描述

我正在尝试将 flask_jwt_extended 实施到我的烧瓶应用程序中。

我的用例是,我想为每个请求设置授权标头。因此,当 @jwt_required 装饰器被装饰到烧瓶路由时,如果授权标头上存在访问令牌,则可以访问它。我尝试了一些解决方案,如下所示:

我使用@app.after_request 将标头附加到每个请求,但它仍然给了我这个响应

{
  "msg": "Missing Authorization Header"
}

这是我的代码:

@app.after_request
def add_headers(resp):
    access_token = session.get("access_token", None)
    if access_token is not None:
        resp.headers["Authorization"] = f"Bearer {access_token}"
        return resp
    return resp

我的登录路线:

@app.route('/', methods=["GET", "POST"])
def login():
    if request.method == "POST":
        form = request.form
        _username = form["username"]
        _password = form["password"]
        for username in Users:
            if username.get(_username):
                if safe_str_cmp(username[_username]["password"],_password):
                    access_token = create_access_token(identity=username[_username]["user_id"], fresh = True)
                    session["access_token"] = access_token
                    res = make_response(redirect(url_for("home")))
                    res.headers["Authorization"] = f"Bearer {access_token}"
                    return res
                else:
                    return "Incorrect password"
        return f"Hello{_username} doesn't exist"
    return render_template("login.html")

这是我的受保护路线:

@app.route('/home')
@jwt_required
def home():
    res = Response(render_template("base.html"))
    return res

我也尝试在路由中添加我的标题,但我指定的标题仍然无法识别并且仍然给我相同的响应消息。这是怎么做的

@app.route('/home')
@jwt_required
def home():
    access_token = session.get("access_token", None)
    print(access_token)
    if access_token is not None:
        res = Response(render_template("base.html"), headers={"Authorization" : f"Bearer {access_token}"})
        return res
    res = Response(render_template("base.html"))
    return res

标签: python-3.xflaskauthorizationflask-jwt-extendedflask-jwt

解决方案


为那些将遇到此问题并尝试实施 OAuth 流程的人编写此内容

不要使用装饰器,而是使用中间件

我相信你应该在中间件中处理这个问题。在中间件中,您可以设置调用函数的第二个参数的授权属性,该参数包含您在 init 函数中传递的当前 wsgi 应用程序环境变量。看下面的代码:

def __init__(self, app):
    self.app = app

def __call__(self, environ, start_response):
    cookie = Request(environ).cookies.get('access_token')
    if cookie is not None:
        environ['HTTP_AUTHORIZATION']='Bearer '+cookie
    return self.app(environ, start_response)

推荐阅读