几天前,我重置了我的本地烧瓶环境,但在删除它之前没有通过 pip freeze
捕获依赖项。因此我不得不重新安装整个堆栈的最新版本。
现在出乎意料的是,我无法再使用表单进行验证。 Flask 声称 CSRF 会丢失。
def register():
form = RegisterForm()
if form.validate_on_submit():
...
return make_response("register.html", form=form, error=form.errors)
我第一次发送 Get
时,我按预期检索了一个空的 form.errors
。现在我填写表格并提交 form.errors
显示: {'csrf_token': [u'CSRF token missing']}
这太奇怪了。我想知道是不是 Flask-WTF 变了,我用错了。
我可以清楚地看到 form.CSRF_token
存在,那么为什么它声称它丢失了?
CSRFTokenField: <input id="csrf_token" name="csrf_token" type="hidden" value="1391278044.35##3f90ec8062a9e91707e70c2edb919f7e8236ddb5">
我从来没有碰过工作模板,但我还是把它贴在这里:
{% from "_formhelpers.html" import render_field %}
{% extends "base.html" %}
{% block body %}
<div class="center simpleform">
<h2>Register</h2>
{% if error %}<p class=error><strong>Error:</strong> {{ error }}{% endif %}
<form class="form-signin" action="{{ url_for('register') }}" method=post>
{{form.hidden_tag()}}
<dl>
{{ render_field(form.name) }}
{{ render_field(form.email) }}
{{ render_field(form.password) }}
{{ render_field(form.confirm) }}
<dd><input type=submit value=Register class='btn btn-primary'>
</dl>
</form>
</div>
{% endblock %}
这是一个新错误吗?
更新:
我已经重新安装了所有东西,但问题仍然存在。
正如 Martijn 所建议的,我正在调试 flask_wtf
中的以下方法:
def validate_csrf_token(self, field):
if not self.csrf_enabled:
return True
if hasattr(request, 'csrf_valid') and request.csrf_valid:
# this is validated by CsrfProtect
return True
if not validate_csrf(field.data, self.SECRET_KEY, self.TIME_LIMIT):
raise ValidationError(field.gettext('CSRF token missing'))
最后一个条件是引发验证错误。
field.data = "1391296243.8##1b02e325eb0cd0c15436d0384f981f06c06147ec"
self.SECRET_KEY = None (? Is this the problem)
self.TIME_LIMIT = 3600
你是对的,HMAC 比较失败了……这两个值每次都不同。
return hmac_compare == hmac_csrf
我在配置中定义了 SECRET_KEY 和 CSRF_SESSION_KEY。
原文由 Houman 发布,翻译遵循 CC BY-SA 4.0 许可协议
如果出现以下情况,Flask-WTF CSRF 基础设施将拒绝令牌:
令牌丢失。这里不是这种情况,您可以在表单中看到令牌。
它太旧了(默认到期时间设置为 3600 秒,或一个小时)。在表单上设置
TIME_LIMIT
属性以覆盖它。这里可能不是这种情况。如果在当前会话中没有找到
'csrf_token'
密钥。您显然可以看到会话令牌,所以它也出来了。如果 HMAC 签名不匹配;签名基于会话中在
'csrf_token'
密钥、服务器端秘密和令牌中的到期时间戳下设置的随机值。排除了前三种可能性后,您需要验证第 4 步失败的原因。您可以在
flask_wtf/csrf.py
文件中调试验证,在validate_csrf()
函数中。对于您的设置,您需要验证会话设置是否正确(特别是如果您不使用默认会话配置),并且您使用的是正确的服务器端机密。表单本身可能有一个
SECRET_KEY
属性集,但在请求中不稳定,或者应用程序WTF_CSRF_SECRET_KEY
键已更改(后者默认为app.secret_key
值) .CSRF 支持是在 0.9.0 版本中添加的,如果您升级了,请查看具体的 CSRF 保护文档。标准 Flask-WTF
Form
类 包含 CSRF 令牌作为隐藏字段,渲染隐藏字段足以包含它: