Django测试中如何通过django-two-factor-auth认证用户访问OTPRequiredMixin视图
问题根因
OTPRequiredMixin会做三层校验,你之前的代码只通过了第一层基础登录校验:
- 校验用户是否已通过Django基础会话登录
- 校验用户账号已绑定激活的OTP设备(即已完成双因素认证启用流程)
- 校验当前会话已经完成OTP二次验证,不是仅输入账号密码的半登录状态
force_login()仅能完成基础会话登录,既没有给用户创建激活的OTP设备,也没有标记会话完成OTP验证,自然会跳转到启用双因素的提示页。
可直接复用的setUp实现
测试环境不需要走真实的扫码、输验证码流程,直接构造激活设备、标记会话验证状态即可:
from django.test import TestCase from django.contrib.auth import get_user_model from django_otp.plugins.otp_totp.models import TOTPDevice from django_otp import login as otp_login from .models import Project class ProjectTestCase(TestCase): def setUp(self): # 创建测试用户,注意用create_user而非create,自动处理密码哈希 self.user = get_user_model().objects.create_user( username='jsmith', first_name='John', last_name='Smith', email='johnsmith@test.com', password='secure' ) # 为用户创建已激活的TOTP设备,标记用户已完成双因素启用流程 self.otp_device = TOTPDevice.objects.create( user=self.user, name='test_device', confirmed=True, # 该参数必须为True,否则会判定为设备未激活 throttle_fail_count=0 ) # 完成基础会话登录 self.client.force_login(self.user) # 标记当前会话已通过OTP验证,跳过验证码校验步骤 otp_login(self.client.session, self.otp_device) # 保存会话修改,确保验证标记持久化生效 self.client.session.save() def test_project_create(self): response = self.client.post( '/project/create/', {'name': 'Test Project', 'description': 'A basic test project'}, follow=True ) self.assertEqual(response.status_code, 200) # 可选校验:确认项目数据确实写入数据库 self.assertTrue(Project.objects.filter(name='Test Project').exists())
注意事项
- 如果你用的是短信、语音类OTP设备,替换对应设备模型即可,核心要求是创建的设备
confirmed=True - 如果要测试「用户已登录但未启用双因素」的权限拒绝场景,只需要去掉创建OTP设备、
otp_login相关的代码即可 - 如果要测试「用户已启用双因素但当前会话未验证OTP」的场景,创建已确认设备但不调用
otp_login即可 CreateView表单校验通过后默认返回302重定向,发请求时加follow=True跟踪重定向,才能拿到最终页面的200状态码
内容的提问来源于stack exchange,提问作者damonmickelsen
相关产品推荐
相关产品推荐

