You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask启用CSRFProtect后Axios请求报CSRF会话令牌缺失错误排查

解决跨服务调用Flask CSRF保护接口的400错误问题

问题根源

你遇到的CSRF session token missing错误,核心原因有两个:

  1. Flask端手动硬写session['csrf_token']不符合flask-wtf的CSRF token生成规范,框架无法识别这个值;
  2. 跨域请求下,Flask的session Cookie没有正确传递到后端,导致session为空,CSRF验证环节找不到对应token。

具体修复步骤

1. 修正Flask后端的CSRF配置与token生成逻辑

移除硬写token的before_request钩子,改用flask-wtf提供的标准方法生成和传递CSRF token:

'''Using flask to create the python ws'''
from flask import Flask, request, session, make_response
from flask_cors import CORS
from flask_wtf.csrf import CSRFProtect, generate_csrf
from dotenv import dotenv_values
from Validator import geia_std_xsd_validation

config = dotenv_values('.env')

ALLOWED_EXTENSIONS = {'xml'}

APP = Flask(__name__)
SECRET_KEY = 'test12'
csrf = CSRFProtect()
origin_array = config['WHITELIST_ARRAY']

# 调整CORS配置,确保跨域Cookie能正常传递
cors = CORS(APP, 
            origins=origin_array, 
            expose_headers=['X-CSRFToken'], 
            supports_credentials=True)

csrf.init_app(APP)
APP.config['SECRET_KEY'] = SECRET_KEY
# 跨域场景下的Cookie配置(根据实际环境调整)
APP.config['SESSION_COOKIE_SAMESITE'] = 'None'  # 跨不同域名时设置为None
APP.config['SESSION_COOKIE_SECURE'] = True      # HTTPS环境下开启,确保Cookie只通过HTTPS传递

APP.vars = {}

def allowed_file(filename):
    return '.' in filename and \
        filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@APP.route('/', methods = ['GET'])
def server_up():
    # 生成标准CSRF token,并设置到响应头
    csrf_token = generate_csrf()
    response = make_response({
        "message": "Server is up",
        "csrf_token": csrf_token
    })
    # 把token放到响应头,方便前端获取
    response.headers['X-CSRFToken'] = csrf_token
    return response

@APP.route('/xsd_validator', methods = ['POST'])
def xsd_validation():
    if request.method == 'POST':
        print('HITTING')
        if len(request.files) <= 0:
            print('No files in response')
            return 'No file sent'

        file = request.files['testFile']
        if file.filename == '':
            print('Blank filename')
            return 'Invalid filename'

        if file and allowed_file(file.filename):
            print('Got into the file statement')
            file_text = file.read()
            errors = geia_std_xsd_validation(file_text)
            return errors

    return 'Nothing Happened'

if __name__ == "__main__":
    APP.run(ssl_context='adhoc', port=6030)  # 测试时用adhoc生成临时HTTPS证书,正式环境用合法证书

2. 调整Express端Axios请求逻辑

不要硬写CSRF token,先从Flask的GET接口获取有效token,再发起POST请求;同时不要手动设置multipart/form-data头,避免丢失表单边界:

const testTHATSHIZZLE = async (req, res) => {
  try {
    // 第一步:获取Flask生成的有效CSRF token
    const csrfRes = await axios.get('https://localhost:6030/', {
      withCredentials: true  // 必须开启,才能接收Flask的session Cookie
    });
    const csrfToken = csrfRes.data.csrf_token;

    // 第二步:构造文件请求
    const file = req.files.testFile
    const submittedFile = new FormData()
    submittedFile.append('testFile', file.data, file.name)

    // 发起POST请求
    const response = await axios.post('https://localhost:6030/xsd_validator', submittedFile, {
      withCredentials: true,
      headers: {
        'X-CSRFToken': csrfToken  // 带上获取到的有效token
        // 不要手动设置Content-Type,FormData会自动生成带boundary的正确头
      }
    })
    res.send(response.data)
  } catch (error) {
    console.log(error.response?.data || error.message)
    res.status(error.response?.status || 500).send(error.response?.data || 'Request failed')
  }
}

关键说明

  • Session Cookie传递:跨域下必须开启withCredentials: true,同时Flask端要设置SESSION_COOKIE_SAMESITE='None'和SESSION_COOKIE_SECURE=True(HTTPS环境),否则浏览器会阻止Cookie跨域传递,导致Flask端session为空。
  • CSRF Token规范:flask-wtf的CSRF验证依赖框架生成的token,手动写入session的csrf_token不会被框架识别,必须用generate_csrf()生成标准token。
  • Content-Type设置:发送FormData时,不要手动设置multipart/form-data,Axios会自动添加正确的boundary参数,否则后端无法解析表单数据。

内容的提问来源于stack exchange,提问作者Thome

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 15:26:24