Hou*_*man 22 python forms flask flask-wtforms
几天前,我已经重置了我的本地烧瓶环境,而没有pip freeze在删除它之前通过a捕获了依赖关系.因此我不得不重新安装整个堆栈的最新版本.
现在突然之间,我无法再使用表单进行验证.Flask声称CSRF将丢失.
def register():
form = RegisterForm()
if form.validate_on_submit():
...
return make_response("register.html", form=form, error=form.errors)
Run Code Online (Sandbox Code Playgroud)
我第一次发送一个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">
Run Code Online (Sandbox Code Playgroud)
我从未触及过工作模板,但我在这里发布了它:
{% 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 %}
Run Code Online (Sandbox Code Playgroud)
这是一个新bug吗?
更新:
我重新安装了一切,问题仍然存在.
正如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'))
Run Code Online (Sandbox Code Playgroud)
最后一个条件是提高验证错误.
field.data = "1391296243.8##1b02e325eb0cd0c15436d0384f981f06c06147ec"
self.SECRET_KEY = None (? Is this the problem)
self.TIME_LIMIT = 3600
Run Code Online (Sandbox Code Playgroud)
你是正确的HMAC比较失败......两个价值观在每次都不同.
return hmac_compare == hmac_csrf
Run Code Online (Sandbox Code Playgroud)
我的配置中定义了SECRET_KEY和CSRF_SESSION_KEY.
Mar*_*ers 20
如果出现以下情况,Flask-WTF CSRF基础架构会拒绝令牌:
令牌丢失.不是这里的情况,您可以在表单中看到令牌.
它太旧了(默认过期时间设置为3600秒或一小时).TIME_LIMIT在窗体上设置属性以覆盖它.可能不是这里的情况.
如果'csrf_token'在当前会话中找不到密钥.您显然可以看到会话令牌,因此也是如此.
如果HMAC签名不匹配; 签名基于'csrf_token'密钥下的会话中设置的随机值,服务器端密钥和令牌中的到期时间戳.
消除了前三种可能性后,您需要验证第四步失败的原因.您可以flask_wtf/csrf.py在validate_csrf()函数中调试文件中的验证.
对于您的设置,您需要验证会话设置是否正确(特别是如果您不使用默认会话配置),并且您使用正确的服务器端密码.表单本身可以SECRET_KEY设置属性但在请求之间不稳定,或者应用程序WTF_CSRF_SECRET_KEY密钥已更改(后者默认为该app.secret_key值).
版本0.9.0中添加了CSRF支持,如果升级,请查看特定的CSRF保护文档.标准的Flask-WTF Form类将CSRF令牌包含为隐藏字段,使隐藏字段足以包含它:
{{ form.hidden_tag() }}
Run Code Online (Sandbox Code Playgroud)
Hou*_*man 16
经过近一天的努力,我终于找到了问题.:(非常感谢Martijn,尽管他的帮助.
实际问题在于最新flask_wtf.csrf的工作方式.制造商完全彻底改革了它.
您必须用{{form.hidden_tag()}}模板替换模板中的
所有内容<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>.
您现在可以通过添加来明确启用CSRF保护CsrfProtect(app).
该文件现在显然是反映了,但我不知道这种情况已经改变,是追鬼.
在不以某种方式通知开发人员的情况下,已弃用的功能是一个大问题.现在升级到最新版本的任何人都会像我一样追逐鬼魂.但它也是我的错,没有拍摄我的依赖关系的快照.经验教训很难.
创建应用程序时:
from flask_wtf.csrf import CsrfProtect
csrf = CsrfProtect()
app = Flask(__name__)
...
csrf.init_app(app)
...
Run Code Online (Sandbox Code Playgroud)