当应用程序移动到docker生产环境时,Flask-WTF CSRF验证失败 [英] Flask-WTF CSRF validation fails when app moved to docker production environment

查看:158
本文介绍了当应用程序移动到docker生产环境时,Flask-WTF CSRF验证失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚为我开发的Flask应用程序设置了我的生产环境。



这个堆栈是:

  Windows Server 2012 R2 
Hyper-V VM
- 运行Ubuntu 14.04
Docker 1.5
- 运行容器:
mysql 5.6
nginx 1.6.3
uwsgi 2.0.10

所以基本上我在Ubuntu中设置了静态IP,80端口转发到nginx容器,数据卷在套接字文件的nginx和uwsgi容器之间共享,最后是用于数据库通信的mysql容器和uwsgi容器之间的链接。



我在本地开发环境中一直使用CSRF进行了一段时间,没有任何问题:

  from flask_wtf import Form 

class UserForm(Form):
...

然后在我的模板中:

 < form> 
{{form.hidden_​​tag()}}
...
< / form>

然而,当我将我的应用程序(不变)移动到上面指定的环境时,我得到:


错误请求



CSRF令牌丢失或不正确。


当我尝试提交表单时。我使用相同的精确的.txt文件与pip来设置我的Flask应用程序。我也验证了CSRF令牌确实在页面的HTML中。任何人都不知道为什么会发生这种情况?



编辑:



回答评论中的问题:我的生产Docker容器和我的开发本地virtualenv中的Flask-WTF和WTForms的版本是相同的。这是我的需求文件,从我的开发环境产生,并用于在Docker容器内设置我的应用程序:

  Flask == 0.10 .1 
Flask-Login == 0.2.11
Flask-Mail == 0.9.1
Flask-Migrate == 1.2.0
Flask-MySQL == 1.2
Flask-Principal == 0.4.0
Flask-SQLAlchemy == 2.0
Flask-Script == 2.0.5
Flask-Security == 1.7.4
Flask- WTF == 0.10.2
Flask-WhooshAlchemy == 0.55a
Jinja2 == 2.7.3
Mako == 1.0.0
MarkupSafe == 0.23
PyMySQL == 0.6.2
SQLAlchemy == 0.7.9
Tempita == 0.5.2
WTForms == 2.0.1
Werkzeug == 0.9.6
Whoosh == 2.6.0
alembic == 0.6.7
blinker == 1.3
chardet == 2.2.1
decorator == 3.4.0
itsdangerous == 0.24
lamson == 1.3.4
passlib == 1.6.2
py-bcrypt == 0.4
pytz == 2014.9
sqlalchemy-migrate == 0.7。 2

据说,由于安装uWSGI,Docker容器中还有一些额外的模块作为我的瓶子应用程序这是额外的。

  argparse(1.2.1)
colorama(0.2.5)
docutils(0.12)
html5lib(0.999)
lockfile(0.10.2)
mock(1.0.1)
MySQL-python(1.2.5)
nose 1.3.6)
python-daemon(2.0.5)
python-modargs(1.7)
请求(2.2.1)
六(1.5.2)
urllib3(1.7.1)
uWSGI(2.0.10)
轮(0.24.0)
wsgiref(0.1.2)


也许我有一个冲突的包?



关于SECRET_KEY和CSRF_SESSION_KEY:我在config.py中定义了SECRET_KEY。我相信没有定义CSRF_SESSION_KEY它将默认为SECRET_KEY。不过,我继续定义了一个CSRF_SESSION_KEY,但似乎没有任何区别。



最后,我研究了从{{form.hidden_​​tag()}}到{{form.csrf_token}}的API更改。他们仍然在最新版本的文档中引用这两种表单。在CSRF页面上,它们具有后者,但是在快速启动中,它们仍然是前者。我不知道这是什么,但只是为了确定我在CSRF页面上实现了版本,如下所示:



init .py:

  from flask_wtf.csrf import CsrfProtect 

CsrfProtect(app)

user_login.html

 <形式> 
{{form.csrf_token}}
...
< / form>

但是我仍然得到同样的回复。



如前所述,Flask-WTF文档遍布全国。所以我一直在尝试各种各样的组合。在此页面的底部: http://flask-wtf.readthedocs.org/ en / latest / csrf.html 引用了错误的导入,所以我从flask_wtf import Form替换了我的




from flask.ext.wtf import表单


仍然没有骰子。感谢您的评论,给我更多的尝试!



我也只是尝试将所有内容整合到一个docker容器中,但我仍然得到相同的结果。 p>

解决方案

基本上我在我的开发config.py文件中有这个:


SERVER_NAME ='localhost:5000'


当我将应用放在生产环境中时,将其更改为:


SERVER_NAME ='192.168.1.66'


应用程序显示。但最终我不得不把它全部评论。从我的研究,只有当你把应用程序放在一个子域,我不是。



如果任何人有更深入的了解为什么会导致CSRF令牌无效,我很乐意听到它..我一直无法跟踪这一切进一步。所以现在我已经把它删除了。


I just set up my production environment for the Flask app I've been developing.

This stack is:

Windows Server 2012 R2 
Hyper-V VM 
    - Running Ubuntu 14.04
Docker 1.5 
    - Running Containers: 
        mysql 5.6
        nginx 1.6.3
        uwsgi 2.0.10

So basically I have a static IP set up in Ubuntu, port 80 getting forwarded to the nginx container, a data volume shared between the nginx and uwsgi containers for a socket file, and finally a link between the mysql container and the uwsgi container for database communication.

I've been using CSRF in the below implementation in my local development environment for awhile now with no issues:

from flask_wtf import Form

class UserForm(Form):
    ...

And then in my template:

<form>
    {{ form.hidden_tag() }}
    ...
</form>

However when I moved my app, unchanged, to the environment specified above, I get:

Bad Request

CSRF token missing or incorrect.

in response when I attempt to submit a form. I am using the same exact requirements.txt file with pip to setup my Flask app. I've also verified that the CSRF token is indeed in the HTML of the page.

Anyone have any clue as to why this is happening?

EDIT:

To answer the questions in the comments: The version of Flask-WTF and WTForms in both my production docker container and my development local virtualenv are the same. Here's my requirements file, spawned from my dev environment and used to set up my app inside the docker container:

Flask==0.10.1
Flask-Login==0.2.11
Flask-Mail==0.9.1
Flask-Migrate==1.2.0
Flask-MySQL==1.2
Flask-Principal==0.4.0
Flask-SQLAlchemy==2.0
Flask-Script==2.0.5
Flask-Security==1.7.4
Flask-WTF==0.10.2
Flask-WhooshAlchemy==0.55a
Jinja2==2.7.3
Mako==1.0.0
MarkupSafe==0.23
PyMySQL==0.6.2
SQLAlchemy==0.7.9
Tempita==0.5.2
WTForms==2.0.1
Werkzeug==0.9.6
Whoosh==2.6.0
alembic==0.6.7
blinker==1.3
chardet==2.2.1
decorator==3.4.0
itsdangerous==0.24
lamson==1.3.4
passlib==1.6.2
py-bcrypt==0.4
pytz==2014.9
sqlalchemy-migrate==0.7.2

That being said, there are a couple extra modules in my docker container due to installing uWSGI as well as my flask app. Here are the additional ones.

argparse (1.2.1)
colorama (0.2.5)
docutils (0.12)
html5lib (0.999)
lockfile (0.10.2)
mock (1.0.1)
MySQL-python (1.2.5)
nose (1.3.6)
python-daemon (2.0.5)
python-modargs (1.7)
requests (2.2.1)
six (1.5.2)
urllib3 (1.7.1)
uWSGI (2.0.10)
wheel (0.24.0)
wsgiref (0.1.2)

Wow, so more than a couple. Perhaps I have a conflicting package?

Regarding SECRET_KEY and CSRF_SESSION_KEY: I had SECRET_KEY defined in my config.py. I was lead to believe that without defining CSRF_SESSION_KEY that it would default to SECRET_KEY. Nevertheless, I went ahead and defined a CSRF_SESSION_KEY, but it didn't seem to make any difference.

Lastly, I looked into the API change from {{ form.hidden_tag() }} to {{ form.csrf_token }}. They still have references to both forms in the docs for the latest version. On the CSRF page, they have the latter, but in the quickstart they still have the former. I'm not sure what is up with this, but just to be certain I implemented the version on the CSRF page as follows:

init.py:

from flask_wtf.csrf import CsrfProtect

CsrfProtect(app)

user_login.html

<form>
    {{ form.csrf_token }}
    ...
</form>

But I still end up getting the same response.

As I said before, the Flask-WTF documentation is all over the place. So I've been trying all sorts of combinations. At the bottom of this page: http://flask-wtf.readthedocs.org/en/latest/csrf.html they reference an incorrect import, so I replaced my

from flask_wtf import Form

with

from flask.ext.wtf import Form

Still no dice. Thanks for the comments though, gave me more to try out!

I also just tried consolidating everything into a single docker container, but I still get the same result.

解决方案

Basically I had this in my development config.py file:

SERVER_NAME = 'localhost:5000'

When I put the app on the production environment, I had to change it to:

SERVER_NAME = '192.168.1.66'

for the app to show up at all. But in the end I had to comment it out altogether. From my research it's only necessary when you're putting the app on a subdomain, which I am not.

If anyone has any more insight into why this would cause CSRF token invalidation, I'd love to hear it.. I've been unable to track this down any further. So for now, I've removed it altogether.

这篇关于当应用程序移动到docker生产环境时,Flask-WTF CSRF验证失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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