Flask在unittest中禁用CSRF

时间:2016-07-27 22:13:15

标签: flask flask-wtforms

在我的项目中__init__.py我有这个:

Letters

我的开发配置文件如下所示:

strptr

在我的unittest setUp中我有这个:

strptr

理论上,在这里将WTF_CSRF_ENABLED设置为False应该可以防止单元测试的CSRF,但是如果我在单元测试时进行POST,我仍然会遇到CSRF错误。我认为这是因为我已经调用了CsrfProtect(app)而WTF_CSRF_ENABLED为True(当我导入app时,它被调用)。如果我在配置文件中设置WTF_CSRF_ENABLED = False,它会按预期工作。

无论如何我可以在启用后禁用CSRF吗?或者我在这里咆哮错误的树?

3 个答案:

答案 0 :(得分:7)

查看csrf_protect的代码,它会在每次请求进入时检查app.config ['WTF_CSRF_METHODS'],以查看此请求类型是否应受CSRF保护。默认情况下,受保护的方法是:

app.config.setdefault('WTF_CSRF_METHODS', ['POST', 'PUT', 'PATCH'])

因为它实际上每次都会检查app.config,只需将其更改为单元测试中的空列表setUp即可解决问题:

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()

Alternetly,它确实用app.before_request()注册csrf保护,所以我认为可以通过修改before request functions来注销它。但我认为走这条路线更有可能在未来的更新中看到问题。

答案 1 :(得分:2)

如果这是一个选项,保持csrf_token并不太难。我能够使用一些正则表达式并使用Flask docs中关于测试的登录功能成功登录到使用csrf_token的应用程序。

def login(self, username, password):
    rv = self.client.get('/login')
    m = re.search(b'(<input id="csrf_token" name="csrf_token" type="hidden" value=")([-A-Za-z.0-9]+)', rv.data)

    return self.client.post('/login', data=dict(
        userName=username,
        password=password,
        csrf_token=m.group(2).decode("utf-8")
    ), follow_redirects=True)

所以我在这里做的是让csrf_token成为第二个捕获组的一部分。这可以很容易地用于在整个应用程序中查找令牌。

答案 2 :(得分:2)

您可以使用配置变量WTF_CSRF_ENABLED将其禁用,

例如

class TestConfig(Config):
    TESTING = True
    WTF_CSRF_ENABLED = False
    ...

app.config['WTF_CSRF_ENABLED'] = False

另请参阅flask-WTF documentation