Flask 在单元测试中禁用 CSRF [英] Flask disable CSRF in unittest
问题描述
在我的项目 __init__.py 中,我有这个:
In my projects __init__.py I have this:
app = Flask(__name__)
app.config.from_object('config')
CsrfProtect(app)
db = SQLAlchemy(app)
我的开发配置文件如下:
My development config file looks like:
import os
basedir = os.path.abspath(os.path.dirname(__file__))
DEBUG = True
WTF_CSRF_ENABLED = True
SECRET_KEY = 'supersecretkey'
SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'project.db')
SQLALCHEMY_TRACK_MODIFICATIONS = False
在我的单元测试设置中,我有这个:
And in my unittest setUp I have this:
from project import app, db
class ExampleTest(unittest.TestCase):
def setUp(self):
app.config['TESTING'] = True
app.config['WTF_CSRF_ENABLED'] = False
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://'
self.app = app.test_client()
db.create_all()
理论上,在这里将 WTF_CSRF_ENABLED 设置为 False 应该可以防止单元测试的 CSRF,但是如果我在单元测试时执行 POST,我仍然会收到 CSRF 错误.我认为这是因为我已经调用了 CsrfProtect(app) 而 WTF_CSRF_ENABLED 为 True (当我导入应用程序时,它被调用).如果我在配置文件中设置 WTF_CSRF_ENABLED = False,它会按预期工作.
In theory, setting WTF_CSRF_ENABLED to False here should prevent CSRF for the unit tests, however I'm still getting CSRF errors if I do a POST while unit testing. I think it is because I have already called CsrfProtect(app) while WTF_CSRF_ENABLED is True (when I import app, it is called). If I set WTF_CSRF_ENABLED = False in the config file, it works as expected.
无论如何我可以在启用CSRF后禁用它吗?还是我在这里吠错了树?
Is there anyway I can disable CSRF after it has already been enabled? Or am I barking up the wrong tree here?
推荐答案
查看 csrf_protect 的代码,每次请求进来都会检查 app.config['WTF_CSRF_METHODS'] 看这个请求类型是否应该受 CSRF 保护.默认情况下,受保护的方法是:
Looking at the code for csrf_protect, it checks app.config['WTF_CSRF_METHODS'] every time a request comes in to see if this request type should be CSRF protected. By default the protected methods are:
app.config.setdefault('WTF_CSRF_METHODS', ['POST', 'PUT', 'PATCH'])
因为它实际上每次都检查 app.config,只需在我的单元测试 setUp 中将其更改为空列表即可解决问题:
Because it actually checks the app.config every time, simply changing this to an empty list in my unit tests setUp resolves the issue:
from project import app, db
class ExampleTest(unittest.TestCase):
def setUp(self):
app.config['TESTING'] = True
app.config['WTF_CSRF_METHODS'] = [] # This is the magic
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://'
self.app = app.test_client()
db.create_all()
或者,它确实使用 app.before_request() 注册了 csrf 保护,所以我认为可以通过修改 before 请求函数.但我认为走这条路更有可能在未来的更新中看到问题.
Alternetly, it does register the csrf protection with app.before_request(), so I think it may be possible to unregister it by modifying the before request functions. But I think going that route would be more likely to see problems on future updates.
这篇关于Flask 在单元测试中禁用 CSRF的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!