我正在尝试为LiveServerTestCase
保护的网站撰写Django Two-Factor Authentication。到目前为止我所拥有的是:
import os
from urllib.parse import urljoin
from django.urls import reverse
from django.conf import settings
from lucy_web.test_factories import UserFactory
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
from selenium import webdriver
chromedriver_path = os.path.join(os.path.dirname(os.path.dirname(settings.BASE_DIR)), 'chromedriver')
assert os.path.isfile(chromedriver_path), f"There should be a chromedriver executable at {chromedriver_path}"
class SeleniumTest(StaticLiveServerTestCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.driver = webdriver.Chrome(chromedriver_path)
cls.password = 'foobar' # Set the password here to avoid using the hashed attribute
cls.user = UserFactory(password=cls.password, is_superuser=True)
def test_login(self):
url = urljoin(self.live_server_url, reverse('dashboard:families'))
self.driver.get(url)
self.driver.find_element_by_name('auth-username').send_keys(self.user.username)
self.driver.find_element_by_name('auth-password').send_keys(self.password)
self.driver.find_element_by_xpath('//input[@value="Next"]').click()
问题在于,此时,驱动程序到达双因素身份验证登录页面,在该页面中需要扫描QR码:
使用测试浏览器过于复杂,所以我想使用override_settings
禁用双因素身份验证以进行测试。但是,查看Django双因素身份验证的General Settings,我无法找到禁用它的设置。
有什么办法可以禁用双因素身份验证来继续这个实时服务器测试用例吗?
答案 0 :(得分:1)
没有内置功能可以执行此操作,但您可以通过扩展中间件轻松完成此操作。只需将您设置中的“OTPMiddleware”与完整的虚线路径交换,然后根据需要将DEBUG更改为其他变量。
from django_otp import DEVICE_ID_SESSION_KEY, _user_is_authenticated
from django_otp.models import Device
from django_otp.middleware import OTPMiddleware, is_verified
from django.conf import settings
class ToggleableOTPMiddleware(OTPMiddleware):
def _verify_user(self, request, user):
"""
Sets OTP-related fields on an authenticated user.
"""
user.otp_device = None
# START CHANGE
if settings.DEBUG:
user.is_verified = lambda: True
else:
user.is_verified = functools.partial(is_verified, user)
# END CHANGE
if _user_is_authenticated(user):
persistent_id = request.session.get(DEVICE_ID_SESSION_KEY)
device = self._device_from_persistent_id(persistent_id) if persistent_id else None
if (device is not None) and (device.user_id != user.id):
device = None
if (device is None) and (DEVICE_ID_SESSION_KEY in request.session):
del request.session[DEVICE_ID_SESSION_KEY]
user.otp_device = device
return user