Python 由于缺少CSRF,表单验证失败
几天前,我重置了本地flask环境,但在删除它之前,我没有通过Python 由于缺少CSRF,表单验证失败,python,forms,flask,flask-wtforms,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=
pip freeze
捕获依赖项。因此,我不得不重新安装整个堆栈的最新版本
现在出乎意料的是,我再也不能用表单验证了。Flask声称CSRF将丢失
def register():
form = RegisterForm()
if form.validate_on_submit():
...
return make_response("register.html", form=form, error=form.errors)
第一次发送Get
时,我检索到一个空的表单。错误与预期一致。
现在我填写表单并提交,然后表单。错误显示:{'csrf_-token':[u'csrf-token missing']}
这太奇怪了。我想知道烧瓶WTF是否已更改,我是否错误地使用了它
我可以清楚地看到表单。CSRF_令牌
存在,为什么它声称它丢失了
CSRFTokenField: <input id="csrf_token" name="csrf_token" type="hidden" value="1391278044.35##3f90ec8062a9e91707e70c2edb919f7e8236ddb5">
最后一个条件是引发验证错误
field.data = "1391296243.8##1b02e325eb0cd0c15436d0384f981f06c06147ec"
self.SECRET_KEY = None (? Is this the problem)
self.TIME_LIMIT = 3600
你是对的,HMAC比较失败……两个值每次都不同
return hmac_compare == hmac_csrf
我在配置中定义了密钥和CSRF会话密钥。如果出现以下情况,Flask WTF CSRF基础结构将拒绝令牌:
- 令牌不见了。这里不是这样,您可以在表单中看到令牌
- 它太旧(默认过期时间设置为3600秒或一小时)。在表单上设置
时间限制
属性以覆盖此限制。这里可能不是这样
- 如果在当前会话中未找到
'csrf\u令牌'
密钥。很明显,您可以看到会话令牌,因此也不存在了
- 如果HMAC签名不匹配;签名基于会话中设置的
'csrf_token'
密钥下的随机值、服务器端机密和令牌中的到期时间戳
排除了前三种可能性后,您需要验证第四步失败的原因。您可以在validate\u csrf()
函数的flask\u wtf/csrf.py
文件中调试验证
对于您的设置,您需要验证会话设置是否正确(特别是在您不使用默认会话配置的情况下),以及您是否使用了正确的服务器端机密。表单本身可能设置了SECRET\u KEY
属性,但在请求之间不稳定,或者appWTF\u CSRF\u SECRET\u KEY
已更改(后者默认为)
CSRF支持是在版本0.9.0中添加的,如果升级了,请查看具体的。标准Flask WTF表单
类将CSRF令牌作为隐藏字段包含,呈现隐藏字段足以包含它:
{{ form.hidden_tag() }}
经过将近一天的努力,我终于发现了这个问题(
非常感谢Martijn的帮助
实际问题在于最新的csrf烧瓶的工作方式。制造商已经对其进行了彻底检修
您必须将模板中的所有{{form.hidden_tag()}}
替换为
现在,您必须通过添加CsrfProtect(app)
来明确启用CSRF保护
现在很明显,这反映了这一点,但我不知道这已经发生了变化,我正在追逐鬼魂
在没有通知开发人员的情况下使用不推荐的功能是一个大问题。现在升级到最新版本的任何人都会像我一样追逐鬼魂。但这也是我的错,没有拍摄我的依赖项的快照。这是一个惨痛的教训。对我来说,问题并不是来自Flask WTF配置不当红色,或缺少标记。它来自环境变量
如果您的Flask服务器没有在本地主机上运行,那么为了使Flask正常工作,您需要设置一个server\u NAME
环境变量。您可能忘记了在某个地方修改server\u NAME
值
例如,在config/settings.py
中可以有类似的内容:
SERVER_NAME = 'my-domain.com'
有关更多信息,请在创建应用程序时查看:
from flask_wtf.csrf import CsrfProtect
csrf = CsrfProtect()
app = Flask(__name__)
...
csrf.init_app(app)
...
您是否接受Cookie?CSRF体系结构要求会话中存在CSRF\u令牌
值且该值有效;它是一个随机值,用于签署令牌,并在发布时用于验证CSRF令牌与表单(以及服务器端机密)是的,Firefox和Chrome都没有阻止cookie。我不明白。因此,为了验证,您确实看到了名为session
set的cookie(前提是您没有将session\u cookie\u NAME
设置为其他名称)?是的。在Eclipse的调试观察列表下,当我进入会话时,我得到以下信息:本地代理:
我有这个问题很久了,意识到这是我的会话\u COOKIE\u SECURE=True
应用程序设置。希望这对其他人有帮助。谢谢Martijn,非常感谢你的帮助。请你看看我的设置日期问题?在我的例子中,应用程序在本地计算机上运行正常,但在托管时崩溃。这是由于作者描述的会话设置不正确。如果遇到相同问题,请在flask应用程序中设置一个常量密钥。您不必替换隐藏的标签()
,但CsrfProtect(应用程序)
当然是必需的。另外,self.SECRET\u KEY
是每个表单的机密,当它设置为None
时,使用应用程序机密。感谢Martijn,我发现了另一个问题。我正在GAE上部署它。似乎flask\u wtf
与flask DebugToolbar
冲突。当我禁用toolbar=DebugToolbarExtension时(应用程序)
,CSRF正在开发人员环境中工作。但只有那些使用flask appengine模板的开发人员受到影响。
:)有趣。我当前的项目正在GAE上使用Flask,但我没有使用任何模板,也没有使用Flask DebugToolbar。如果我使用,我会注意任何问题。我现在有几个项目同时使用调试工具栏和CSRF保护窗体。如果您只使用FlaskForm窗体,则根本不需要CSRFProtect
SERVER_NAME = 'my-domain.com'
from flask_wtf.csrf import CsrfProtect
csrf = CsrfProtect()
app = Flask(__name__)
...
csrf.init_app(app)
...