【发布时间】:2017-01-08 16:07:17
【问题描述】:
看起来像一个简单的错误 - 由于“CSRF 令牌丢失”错误而无法完成的表单提交 - 已经变成了一天的头发拉扯。我浏览了每一篇与 Flask 或 Flask-WTF 相关的 SO 文章以及缺少 CSRF 令牌,但似乎没有任何帮助。
以下是详细信息:
在Martijin's guidelines 之后回答之前的问题:
Flask-WTF CSRF 基础设施在以下情况下拒绝令牌:
1) 令牌丢失。这里不是这样,你可以在表单中看到token。
令牌肯定存在于我的表单中,并且已成功发布
2) 它太旧了(默认过期设置为 3600 秒,或一小时)。 在表单上设置 TIME_LIMIT 属性以覆盖它。可能不是 案例在这里。
对我来说也可以 - 令牌在默认到期时间之内
3) 如果在当前会话中没有找到 'csrf_token' 密钥。你可以 显然看到了会话令牌,所以也出来了。
就我而言,会话['csrf_token'] 已正确设置并被 Flask 看到
4) 如果 HMAC 签名不匹配;签名是基于 在 'csrf_token' 键下的会话中设置的随机值, 服务器端密钥,以及令牌中的到期时间戳。
这是我的问题。提交表单的 CSRF 和会话 CSRF 之间的 HMAC 比较失败。但我不知道如何解决它。我已经非常绝望(与其他提问者一样)深入研究 Flask-WTF 代码并设置调试消息以了解发生了什么。据我所知,它的工作原理是这样的:
1) "form.py" (Flask-WTF) 中的generate_csrf_token() 想要生成一个 CSRF 令牌。所以它调用:
2) generate_csrf() 在“csrf.py”中。如果不存在,该函数会生成一个新会话['csrf_token']。 在我的情况下,这种情况总是会发生 - 尽管其他会话变量似乎在请求之间持续存在,但我的调试显示我从不在我的会话开始时有一个“csrf_token”一个要求。这正常吗?
3) 当我在模板上渲染隐藏字段时,生成的标记被返回并可能合并到表单变量中。 (再次,调试表明此令牌存在于表单中并正确提交和接收)
4) 接下来,提交表单。
5) 现在调用 csrf.py 中的validate_csrf。但是由于另一个请求已经发生,并且 generate_csrf() 已经生成了一个新的会话 CSRF 令牌,这两个令牌的两个时间戳(在会话中和来自表单)将不匹配。由于 CSRF 部分由到期日期组成,因此验证失败。
我怀疑问题出在第 2 步,即为每个请求生成一个新令牌。但我不知道为什么我的会话中的其他变量在请求之间持续存在,而不是“csrf_token”。
SECRET_KEY 或 WTF_CSRF_SECRET_KEY 也没有什么奇怪的地方(它们已正确设置)。
有人有什么想法吗?
【问题讨论】:
-
我最后不得不清除我的 cookie。对于阅读本文的其他人来说,这可能是一个快速的解决方案。
标签: python session flask wtforms flask-wtforms