使用扩展的 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
我知道如何使用这个库创建令牌,以及如何将令牌放入响应正文中:
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