python - 由于缺少 CSRF,表单验证失败

标签 python forms flask flask-wtforms

几天前,我重置了本地 flask 环境,但在删除之前没有通过 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。

最佳答案

Flask-WTF CSRF 基础设施在以下情况下拒绝 token :

  • token 丢失。这里不是这样,你可以在表单中看到token。

  • 它太旧了(默认过期设置为 3600 秒或一小时)。在表单上设置 TIME_LIMIT 属性以覆盖它。可能不是这里的情况。

  • 如果在当前 session 中没有找到 'csrf_token' key 。您显然可以看到 session token ,所以它也出来了。

  • 如果 HMAC 签名不匹配;签名基于 'csrf_token' key 下 session 中设置的随机值、服务器端 secret 和 token 中的到期时间戳。

排除了前三种可能性后,您需要验证第四步失败的原因。您可以在 flask_wtf/csrf.py 文件中的 validate_csrf() 函数中调试验证。

对于您的设置,您需要验证 session 设置是否正确(特别是如果您不使用默认 session 配置),并且您使用的是正确的服务器端 key 。表单本身可能设置了 SECRET_KEY 属性但在请求之间不稳定,或者应用程序 WTF_CSRF_SECRET_KEY 键已更改(后者默认为 app.secret_key value )。

CSRF 支持是在 0.9.0 版本中添加的,请查看具体的 CSRF protection documentation如果你升级了。标准的 Flask-WTF Form包含 CSRF token 作为隐藏字段,渲染隐藏字段足以包含它:

{{ form.hidden_tag() }}

关于python - 由于缺少 CSRF,表单验证失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21501058/

相关文章:

python - 从零开始的搜索引擎

python - python 中的 os.read(0,) 与 sys.stdin.buffer.read()

python - 在网络界面中显示以numpy表示的birmap [Python]

php - 通过表单更新中的 POST 方法传递表单值

python - Flask 的上下文堆栈的目的是什么?

Python flask : Getting an 'OperationalError' object is not callable when inserting to database

python - 如何在Python列表中添加和扩展新行?

ruby-on-rails-3 - 检测表单是否使用 ruby​​ on rails 提交?

javascript - 检索通过 POST 方法表单传递的值

python - Flask - 从函数获取路由 URL