关于Flask SessionId 跨域,客户端保存cookie问题
-
问题背景:
我最近有个前后端分离的需求:前端使用axios跨域请求,后端flask使用cookie验证。但过程遇到前端不保存cookie和前端请求不携带cookie的问题。
-
问题分析
我后端有两个api,一个用于登陆验证,验证成功则返回一个cookie用于其他需要验证的接口请求
# 创建响应对象 response = make_response() # 设置 cookie response.set_cookie('user_id', value=str(user[0]), max_age=3600, samesite='None', secure=True) # 一小时的秒数 # 添加响应头 session[user[0]] = user[0] # 将用户 ID 存储在会话中 print(session) return response
其他需要验证的API效验器
# 要求登录的装饰器 def login_required(func): def wrapper(*args, **kwargs): user_id = request.cookies.get('user_id',None) print(user_id) print(session) if user_id is None or user_id not in session or session[user_id] != user_id: return jsonify({ "msg": "请登录后操作", "code": 403 }) return func(*args, **kwargs) return wrapper
我的验证流程很简单:验证成功返回验证所需的cookie,客户端接收保存,在请求其他需要验证的接口时,携带上验证所需的cookie,服务端接收到cookie 后验证内容是否存在session对话中,存在则放行。
-
问题解决
跨域问题:前端配置好,后端也要配置,pip install flask_cors
from flask_cors import CORS def create_app(test_config=None): # create and configure the app app = Flask(__name__, instance_relative_config=True) #配置此处 CORS(app, supports_credentials=True)
axios无法自动携带cookie需要配置
import axios from "axios"; //创建一个新的请求实例instance,instance.的用法和axios.的用法一致,可以使用instance({})、instance.get()、instance.post() const instance = axios.create({ baseURL: 'http://127.0.0.1:5000/', timeout: 60000, withCredentials: true, //配置此处,允许携带cookie发送请求 });
-
后端set-cookie无法保存前端问题:
首先,后端没有任何配置的时候,请求发现,SameSite 值一直为Lax, 如果需要信任并保存cookie就必须,在后端设置SameSite = None,Secure=True,我看过几篇文章提到修改浏览器设置,关掉某些设置就能解决。但我觉得,这不是纯纯扯淡吗,不解决问题,逃避问题是吧,笑死了。
观察发现两个cookie,第一个是我自己配置的user_id用于验证,另一个是flask自动返回的session ,它的值就是sessionid。
解决办法
自定义的set-cookie:user_id
response.set_cookie('user_id', value=str(user[0]), max_age=3600, samesite='None', secure=True) # 一小时的秒数
服务器自动返回的,在flask官网找到解决办法Security Considerations — Flask Documentation (3.0.x) (palletsprojects.com),session id一定要配置才能保存到客户端,否则你每次请求的sessionId都是不同因此,无法取出你原本保存的
session[user[0]] = user[0] ,没有id就找不到,访问不了对应的session数据
import os
from flask import Flask
from datetime import timedelta
from flask_cors import CORS
def create_app(test_config=None):
# create and configure the app
app = Flask(__name__, instance_relative_config=True)
#配置此处
CORS(app, supports_credentials=True)
app.config.update(
SESSION_COOKIE_SECURE=True,
SESSION_COOKIE_HTTPONLY=True,
SESSION_COOKIE_SAMESITE='None',
)
解决后:现在都正常了,每次axios请求都会自动携带这两个cookie,后端也能解析出对应的session了