引入 django-axes 后测试出现问题

发布: (2026年1月4日 GMT+8 16:33)
3 min read
原文: Dev.to

Source: Dev.to

背景

什么是 django-axes?

django-axes 是一个 Django 包,用于监控登录尝试并根据认证设置锁定用户。它有助于防止暴力破解攻击。

官方文档

我为什么使用 django-axes

我在一个协作项目中开发一个带登录功能的小应用。为了防止暴力破解攻击,我们想限制登录尝试次数,于是决定引入 django-axes

问题

在实现 django-axes 后,我运行了所有测试。许多之前通过的测试开始失败。所有失败都与登录功能有关,因为测试中没有包含请求对象。

当测试使用 client.login(如下所示)时,用户会在没有 HTTP 请求的情况下被认证。然而,django-axes 通过检查请求来判断用户是否已认证,导致了这些失败。

失败的模式(使用 client.login

self.user = User.objects.create_user(
    username="login_user",
    email="login@example.com",
    password="LoginPass123",
)

self.client.login(email="login@example.com", password="LoginPass123")

正常的模式(使用 client.post

self.user = User.objects.create_user(
    username="login_user",
    email="login@example.com",
    password="LoginPass123",
)

self.client.post(
    self.login_url,
    {"email": "login@example.com", "password": "LoginPass123"},
    REMOTE_ADDR="192.168.1.1",
)

解决方案

我找到了两种实用的解决办法。

1. 在测试中禁用 django-axes

在测试配置中设置 AXES_ENABLE = False,即可在测试期间关闭 django-axes 检查。
当需要测试与 django-axes 相关的功能时,再将其重新设为 AXES_ENABLE = True

在测试中禁用 Axes 组件

这种做法可以让你仅在真正需要的测试中启用 django-axes 行为。

2. 使用 force_login()

force_login() 绕过了 django-axes 所挂钩的认证过程。对于与登录验证本身无关的测试,使用 force_login() 替代 client.login() 是合理的。

force_login 文档

正常的模式(使用 force_login

self.user = User.objects.create_user(
    username="login_user",
    email="login@example.com",
    password="LoginPass123",
)

self.client.force_login(self.user)

如前所述,使用 client.post() 也能正常工作,因为它会包含请求对象。

结论

django-axes 是一个非常有用的包,能够提升应用的安全性。但在引入它时,需要注意测试中认证的处理方式。根据应用架构和测试策略,选择最合适的方案——要么在测试中禁用 django-axes,要么使用 force_login() / client.post() 进行认证。

希望这能帮助遇到类似问题的朋友。

Back to Blog

相关文章

阅读更多 »