Flask中CSRF Token过期及每次请求生成新Token问题求助
解决Flask-WTF CSRF Token过期与每次请求生成新Token的问题
问题根源
你当前的代码存在两个核心问题:
- 调用
generate_csrf()时未加refresh=True参数,该方法默认只会返回已存在的CSRF Token,不会生成并替换session中的旧Token。 - 页面加载时生成的Token会随着session过期而失效,长时间打开页面后提交表单,使用的仍是过期的旧Token,导致验证失败。
解决方案
1. 后端:每次请求强制生成新CSRF Token
修改generate_csrf()调用,添加refresh=True参数来强制生成新Token,并确保session的有效期随请求刷新:
from flask import Flask, redirect, url_for, render_template_string, session from flask_wtf.csrf import CSRFProtect, generate_csrf from datetime import timedelta app = Flask(__name__) app.secret_key = 'key' csrf = CSRFProtect(app) # 设置session过期时间,测试用10秒,生产环境可设为1小时或更长 app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(seconds=10) # 每次请求自动刷新session的过期时间 app.config['SESSION_REFRESH_EACH_REQUEST'] = True html= """ <form method="POST" action="{{ url_for('redirect_route') }}" id="myForm"> <input type="hidden" name="csrf_token" id="csrfToken" value="{{ csrf_token() }}"> <button type="submit">Redirect</button> </form> <script> // 定时刷新CSRF Token,间隔设为session过期时间的一半,避免过期 setInterval(() => { fetch('/get-new-csrf') .then(response => response.json()) .then(data => { document.getElementById('csrfToken').value = data.csrf_token; }); }, 5000); </script> """ @app.route('/') def home(): # 强制生成新的CSRF Token并更新session generate_csrf(refresh=True) session.permanent = True return render_template_string(html) @app.route('/redirect', methods=['POST']) def redirect_route(): generate_csrf(refresh=True) session.permanent = True return redirect(url_for('home')) # 新增接口,用于前端获取最新CSRF Token @app.route('/get-new-csrf') def get_new_csrf(): new_token = generate_csrf(refresh=True) return {'csrf_token': new_token} app.run(debug=True)
2. 前端:定时更新Token避免过期
通过JavaScript定时调用后端接口获取最新Token,更新表单中的隐藏字段,确保每次提交时使用的都是有效Token。设置的刷新间隔应短于session过期时间(比如session设10秒,刷新间隔设5秒),这样就能避免页面长时间打开后Token失效的问题。
关键配置说明
generate_csrf(refresh=True):强制生成新的CSRF Token,并覆盖session中存储的旧Token,实现每次请求生成独立Token的需求。SESSION_REFRESH_EACH_REQUEST=True:每次用户发起请求时,自动刷新session的过期时间,只要用户有操作,session就不会轻易过期。- 前端定时刷新:解决页面长时间处于后台未操作,session过期后提交表单的问题,确保提交时Token始终有效。
内容的提问来源于stack exchange,提问作者Caiden
相关产品推荐
相关产品推荐

