表单验证因失去CSRF而失败 [英] Form validation fails due missing CSRF

查看:390
本文介绍了表单验证因失去CSRF而失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

前几天我已经重置我的本地烧瓶环境,而没有通过 pip freeze 捕获依赖,然后删除它。因此,我不得不重新安装整个堆栈的最新版本。



现在,我不再能够使用表单进行验证。 Flask声明CSRF将会丢失。

  def register():
form = RegisterForm()
if form.validate_on_submit():
...
返回make_response(register.html,form = form,error = form.errors)
获取我检索一个空的 form.errors code>按预期。
现在我填写表单并提交, form.errors 显示: {'csrf_token':[u'CSRF token missing ']}



这太奇怪了。我不知道Flask-WTF是否改变了,我错误地使用了它。



我可以清楚地看到 form.CSRF_token 存在,那么它为什么声称它失踪?

  CSRFTokenField:< input id =csrf_tokenname =csrf_token type =hiddenvalue =1391278044.35 ## 3f90ec8062a9e91707e70c2edb919f7e8236ddb5> 

我从来没有碰过工作模板,但是我在这里发表:

  {%from_formhelpers.htmlimport render_field%} 
{%extendsbase.html%}
{%block body%}
< div class =center simpleform>
< h2>注册< / h2>
{%if error%}< p class = error>< strong>错误:< / strong> {{error}} {%endif%}
{{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%}

这是一个新的bug吗?
$ b

更新:

我已经重新安装了所有内容,问题仍然存在。

正如Martijn所建议的,我正在调试 flask_wtf 中的以下方法:

  def validate_csrf_token(self,field):
如果不是self.csrf_enabled:
返回True $ b $如果hasattr(request, 'csrf_valid')和request.csrf_valid:
#这是验证的CsrfProtect
返回True
如果不是validate_csrf(field.data,self.SECRET_KEY,self.TIME_LIMIT):
提交ValidationError(field.gettext('CSRF token missing'))

最后一个条件是提高验证错误。

  field.data =1391296243.8 ## 1b02e325eb0cd0c15436d0384f981f06c06147ec
self.SECRET_KEY = None(?这是问题)
self.TIME_LIMIT = 3600

你说得对,HMAC比较失败.. ..both值每次都是不同的。

  return hmac_compare == hmac_csrf 

在我的config中定义了SECRET_KEY和CSRF_SESSION_KEY。
<如果符合以下条件,Flask-WTF CSRF基础架构将拒绝一个标记:


  • 令牌丢失。在这里不是这种情况,你可以在窗体中看到令牌。
  • 它太旧了(默认过期设置为3600秒,或者一个小时)。在窗体上设置 TIME_LIMIT 属性来覆盖这个属性。如果在当前会话中找不到'csrf_token'键,则可能不是这种情况。

  • 您可以看到会话令牌,所以也不会发生。 签名是基于会话中在'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 class 包含 CSRF标记作为隐藏字段,呈现隐藏字段足以包含它:

  {{form.hidden_​​tag()}} 


A few days ago I have reset my local flask environment without having captured the dependencies via a pip freeze before I deleted it. Hence I had to re-install the latest version of the entire stack.

Now out of the blue I am no longer able to validate with forms. Flask claims CSRF would be missing.

def register():
    form = RegisterForm()
    if form.validate_on_submit():
       ...
    return make_response("register.html", form=form, error=form.errors)

The first time I send a Get I retrieve an empty form.errors as expected. Now I fill out the form and submit it and form.errors is showing: {'csrf_token': [u'CSRF token missing']}

This is so strange. I wonder if Flask-WTF has changed and I am using it wrongly.

I can clearly see the form.CSRF_token exists, so why is it claiming it was missing?

CSRFTokenField: <input id="csrf_token" name="csrf_token" type="hidden" value="1391278044.35##3f90ec8062a9e91707e70c2edb919f7e8236ddb5">

I never touched the working template, but I post it here nonetheless:

{% 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 %}

Is this a new bug?

UPDATE:

I have reinstalled everything and the problem persists.

As Martijn suggested, I am debugging into the the following method in 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'))

The last condition is raising the validation error.

field.data = "1391296243.8##1b02e325eb0cd0c15436d0384f981f06c06147ec"
self.SECRET_KEY = None (? Is this the problem)
self.TIME_LIMIT = 3600

And you were right the HMAC comparison fails....both values are in every time different.

return hmac_compare == hmac_csrf

I have both SECRET_KEY and CSRF_SESSION_KEY in my config defined.

解决方案

The Flask-WTF CSRF infrastructure rejects a token if:

  • the token is missing. Not the case here, you can see the token in the form.

  • it is too old (default expiration is set to 3600 seconds, or an hour). Set the TIME_LIMIT attribute on forms to override this. Probably not the case here.

  • if no 'csrf_token' key is found in the current session. You can apparently see the session token, so that's out too.

  • If the HMAC signature doesn't match; the signature is based on the random value set in the session under the 'csrf_token' key, the server-side secret, and the expiry timestamp in the token.

Having eliminated the first three possibilities, you need to verify why the 4th step fails. You can debug the validation in flask_wtf/csrf.py file, in the validate_csrf() function.

For your setup, you need to verify that the session setup is correct (especially if you don't use the default session configuration), and that you are using the correct server-side secret. The form itself could have a SECRET_KEY attribute set but is not stable across requests, or the app WTF_CSRF_SECRET_KEY key has changed (the latter defaults to the app.secret_key value).

The CSRF support was added in version 0.9.0, do check out the specific CSRF protection documentation if you upgraded. The standard Flask-WTF Form class includes the CSRF token as a hidden field, rendering the hidden fields is enough to include it:

{{ form.hidden_tag() }}

这篇关于表单验证因失去CSRF而失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆