使用gunicorn和Flask时出现CSRF令牌错误

Nik*_*kar 5 flask gunicorn flask-wtforms

我开发了一个网络应用程序,其中包含用户登录和注册的功能。我已经按照文档和教程完成了所有操作,并且 Flask 服务器一切正常。

问题是:我使用gunicorn并启动一个Web服务器,(localhost:8000)在几种不同的浏览器(Linux上的Brave和Firefox,以及Android上的Brave)上打开地址,我只能从一个客户端登录(单个或多个不同的用户)。当我尝试从另一个请求执行此操作时,它会抛出 400 Bad Request(CSRF 会话令牌丢失或 CSRF 会话令牌不匹配)。

现在,使用 Flasks Server 时不会发生这种情况。它只发生在使用gunicorn时。

我已将应用程序部署到 Heroku(使用免费计划),并且我希望多个用户同时登录。我的应用程序拥有的所有其他表单都会发生这种情况。

所有环境变量、密钥均已正确配置,使用 Flask Server 时一切都按预期运行。除此以外,使用 Gunicorn 不会导致任何其他问题。有时,从单个客户端登录也不起作用。

任何帮助,将不胜感激。我已经查看了其他相关的线程/问题,但他们没有提到我遇到的问题

小智 6

抱歉回复晚了(也许对以后的人有帮助)

简短的回答:
使用:

with app.app_context():
    your code
Run Code Online (Sandbox Code Playgroud)

代替 :

app.app_context().push()
Run Code Online (Sandbox Code Playgroud)

永远不会关闭

长答案:

我猜你使用 Flask-WTF 来管理 CSRF,如果是,则有一个 if 块(https://github.com/wtforms/flask-wtf/blob/0.15.x/src/flask_wtf/csrf.py#L53)在generate_csrf函数中,它在生成新的CSRF令牌之前检查flask g变量。它工作得很好,但是当 g 变量没有在每个新请求上重新初始化时(原因见下文),它会在尝试登录的不同用户之间产生冲突。

不重新初始化 Flask g 变量的主要原因是手动推送的应用程序上下文(通常通过:app.app_context().push())但未关闭,在这种情况下,应用程序上下文永远不会被拆除,请参阅:Flask app当 DEBUG 为 false 时,.teardown_appcontext 不会被调用

最后,我认为 Flask DEBUG 模式中有一些东西,它强制拆除应用程序上下文并重新初始化 g 变量。