Flask-WTF 的校验到底在哪一步报什么错?CSRF token 里装了什么、什么情况下会失败?AJAX 的 X-CSRFToken 请求头为什么有时候没用?这篇用 test_client 把每一种错误信息逐个打印出来。
email_validator 已安装
上一篇:Flask-Login 登录流程;下一篇:Flask-Migrate 基础。
渲染结果: <input id="csrf_token" name="csrf_token" type="hidden" value="Ijg4MzJkNWUwYmQ0ZWU0ZjIxYzZjYTAzYmMyYmZmOTBmZjNkMTk4OTYi.ar8q8g.sAeB3FS6Q61qwTk9l22abpUx… csrf_token = Ijg4MzJkNWUwYmQ0ZWU0ZjIxYzZjYTAzYmMyYmZmOTBmZjNkMTk4OTYi.ar8q8g.sAeB3FS6Q61qwTk9l22abpUxbLY 结构: 3 段 | 第 1 段(base64)解码 → b'"8832d5e0bd4ee4f21c6ca03bc2bff90ff3d19896"' (签名过的是 session 里的随机串,不是用户信息) session 里多了键: ['csrf_token']
合法数据 + token → 200 {'age': 30, 'agree': True, 'email': 'a@b.co', 'username': 'annie'}
合法数据,没有 token → 400 {'csrf_token': ['The CSRF token is missing.']}
用户名太短 → 400 {'username': ['长度 3-10']}
用户名是 admin(自定义校验) → 400 {'username': ['用户名已被占用(自定义校验)']}
邮箱格式不对 → 400 {'email': ['邮箱格式不对']}
年龄 17 → 400 {'age': ['18-120']}
年龄不是数字 → 400 {'age': ['Not a valid integer value.', '18-120']}
两次密码不一致 → 400 {'confirm': ['两次密码不一致']}
不勾选同意 → 400 {'agree': ['必须同意']}
什么都不填 → 400 {'age': ['18-120'], 'agree': ['必须同意'], 'email': ['This field is required.'], 'password': ['This field is required.'], 'username': ['必填']} GET /signup → 200 {'errors': {}, 'ok': False, 'submitted': False} 正常: 200
用别的会话的 token → 400 {'csrf_token': ['The CSRF tokens do not match.']}
篡改 token 末尾 → 400 {'csrf_token': ['The CSRF token is invalid.']}
WTF_CSRF_TIME_LIMIT=1 秒,等 2.5 秒再提交(时间戳精度是秒,要等够 2 秒才保证 age > 1) → 400 {'csrf_token': ['The CSRF token has expired.']}
WTF_CSRF_ENABLED=False(测试时常用)→ 200 表单数据 + 头 X-CSRFToken → 400 {'csrf_token': ['The CSRF token is missing.']}
JSON 请求体 + 头 X-CSRFToken → 400 {'csrf_token': ['The CSRF token is missing.']}只有 FlaskForm 不认请求头;用了 CSRFProtect 就可以(见下一节)。
POST /p 没有 token → 400 <!doctype html> <html lang=en> <title>400 Bad Request</title> <h1>Bad Request</h1> <p>The CSRF token is missin 带 token 的 POST → 200
没有文件 → {'f': ['This field is required.']}
a.exe → {'f': ['只允许 png/jpg']}
a.png → {'errors': {}, 'ok': True}