使用扩展的 Flask jwt 将令牌存储在浏览器 cookie 中

Store tokens in browser cookies with Flask jwt extended

我知道如何使用这个库创建令牌,以及如何将令牌放入响应正文中:

access_token = create_access_token(identity = token_identity)
refresh_token = create_refresh_token(identity = token_identity)
set_access_cookies({"login": True}, access_token)
set_refresh_cookies({"login": True}, refresh_token)

但是,当它与我的烧瓶应用程序一起使用时,我的浏览器 cookie 中没有存储任何内容。 除了使用 set_access_cookies 或 set_refresh_cookies 之外,我还需要做些什么来将令牌存储在 cookie 中吗?

一个代码示例:

import logging
from flask import Blueprint, render_template, redirect, url_for, request, current_app as app, jsonify
from flask_login import login_user, logout_user, login_required
from werkzeug.security import generate_password_hash, check_password_hash
from .models import User
from . import db, login_manager, login_serializer, jwt
from flask_jwt_extended import (create_access_token, 
create_refresh_token, jwt_required, jwt_refresh_token_required, get_jwt_identity, get_raw_jwt, set_access_cookies,
set_refresh_cookies, unset_jwt_cookies)


def set_response_cookies(token_identity, resp=None, token_types=["access", "refresh"]):
    """
    Helper function to set cookies 
    """
    logging.warning("Setting cookies")
    token_types.sort()
    if token_types == ["access", "refresh"]:
        access_token = create_access_token(identity = token_identity)
        refresh_token = create_refresh_token(identity = token_identity)
        if not resp:
            resp = jsonify({"access_token": access_token, "refresh_token": refresh_token})
        set_access_cookies(resp, access_token)
        set_refresh_cookies(resp, refresh_token)
        return resp 
    elif token_types == ["access"]:
        access_token = create_access_token(identity = token_identity)
        if not resp:
            resp = jsonify({"access_token": access_token})
        set_access_cookies(resp, access_token)
        return resp 
    elif token_types == ["refresh"]:
        refresh_token = create_refresh_token(identity = token_identity)
        if not resp:
            resp = jsonify({"refresh_token": refresh_token})
        set_refresh_cookies(resp, refresh_token)
        return resp 
    else:
        raise ValueError("Wrong Call to this function")

@auth.route('/signup', methods=['POST'])
def signup_post():
    email = request.form.get('email')
    name = request.form.get('name')
    password = request.form.get('password')

    user = User.objects(email=email) 
    if user:  # Email already exist.  
        return redirect(url_for('auth.signup')), 409
    logging.warning("User not existing")
    new_user = User(email=email, name=name, password=generate_password_hash(password, method='sha256'))
    new_user.save()
    set_response_cookies(email, ["access", "refresh"])
    return redirect(url_for('auth.login')), 200

你可以利用set_cookie()

在 cookie 中存储令牌:

from flask import make_response

@app.route('/')
def index():
    response = make_response(render_template(...))
    response.set_cookie('access_token', 'YOUR_ACCESS_TOKEN')
    response.set_cookie('refresh_token', 'YOUR_REFRESH_TOKEN')
    return response

从 cookie 中检索令牌:

from flask import request

@app.route('/')
def index():
    access_token = request.cookies.get('access_token')

通过这种方式,您可以将令牌存储在 cookie 中,并从 cookie 中检索令牌。

检查您的回复中是否有多个 Set-Cookie header:

The HTTP header Set-Cookie is a response header and used to send cookies from the server to the user agent.

我还建议您检查您的应用配置。这是我与 jwt-extended:

相关的配置
JWT_SECRET_KEY = os.getenv("JWT_SECRET_KEY", 'local-secret')
JWT_TOKEN_LOCATION = ['cookies']
JWT_ACCESS_TOKEN_EXPIRES = datetime.timedelta(seconds=1800)
JWT_COOKIE_SECURE = False
JWT_REFRESH_TOKEN_EXPIRES = datetime.timedelta(days=15)
JWT_COOKIE_CSRF_PROTECT = True 
JWT_ACCESS_CSRF_HEADER_NAME = "X-CSRF-TOKEN-ACCESS"
JWT_REFRESH_CSRF_HEADER_NAME = "X-CSRF-TOKEN-REFRESH"

问题可能出在客户端,而不是服务器端。我的应用程序使用 axios,为了让它为我工作,我必须在将它导入 javascript 文件后添加 axios.defaults.withCredentials = true

import axios from 'axios'
axios.defaults.withCredentials = true