如何重写Django双因素认证默认登录成功响应
Django双因素认证登录后无法返回自定义HttpResponse的问题
我在登录视图中使用Django Two Factor Authorization,通过插件管理器注册了TwoFactorPlugin。目前遇到的问题是:尽管我在视图中返回自定义的HttpResponse,系统却始终跳转到LOGIN_REDIRECT_URL;若移除该配置,则会默认重定向到accounts/profile/(双因素认证的默认登录成功地址)。请问是否可以重写此逻辑以返回视图的HttpResponse?是否有其他实现方法或建议?
views.py
from two_factor.views import LoginView as TwoFactorLoginView @login_required def login_success(request): success_message = f"User logged in successfully." return HttpResponse(success_message) class TwoFactor_LoginView(TwoFactorLoginView): def form_valid(self, form): response = super().form_valid(form) # plugin_response is an HttpResponse return from the plugin "two_factor" plugin_response = PluginManager.perform_action( "two_factor", self.request, email=self.request.user.email, password=form.cleaned_data.get("password"), token=self.request.POST.get("token"), ) # If the plugin action returns an HttpResponse, use it instead if isinstance(plugin_response, HttpResponse): return plugin_response return response
urls.py
path("login/", TwoFactor_LoginView.as_view(), name="login"), path("login_success/", login_success, name="login_success"),
settings.py
LOGIN_URL = "login/" LOGIN_REDIRECT_URL = "/login_success/"
解决方案
问题核心是TwoFactorLoginView父类的form_valid方法在执行时,已经完成登录并生成了重定向响应,你后续返回的自定义响应会被覆盖。以下是两种可行的解决思路:
方法1:重写get_success_url并调整form_valid逻辑
如果插件返回的是重定向地址,或你需要动态控制跳转目标,可以通过重写get_success_url实现,同时调整form_valid避免父类的重定向覆盖:
class TwoFactor_LoginView(TwoFactorLoginView): def get_success_url(self): # 先执行插件逻辑获取目标地址 plugin_response = PluginManager.perform_action( "two_factor", self.request, email=self.request.user.email, password=self.request.POST.get("password"), token=self.request.POST.get("token"), ) if isinstance(plugin_response, HttpResponseRedirect): return plugin_response.url # 自定义默认跳转地址,替代全局的LOGIN_REDIRECT_URL return reverse("login_success") def form_valid(self, form): # 执行父类的登录逻辑,但不返回其重定向响应 super().form_valid(form) # 检查插件是否返回直接响应 plugin_response = PluginManager.perform_action( "two_factor", self.request, email=self.request.user.email, password=form.cleaned_data.get("password"), token=self.request.POST.get("token"), ) if isinstance(plugin_response, HttpResponse): return plugin_response # 否则跳转到自定义成功地址 return HttpResponseRedirect(self.get_success_url())
方法2:完全手动控制登录与响应
跳过父类form_valid的重定向逻辑,手动完成登录并返回自定义响应:
class TwoFactor_LoginView(TwoFactorLoginView): def form_valid(self, form): # 手动执行登录(父类form_valid的核心逻辑就是调用form.save()) form.save() # 执行插件逻辑 plugin_response = PluginManager.perform_action( "two_factor", self.request, email=self.request.user.email, password=form.cleaned_data.get("password"), token=self.request.POST.get("token"), ) if isinstance(plugin_response, HttpResponse): return plugin_response # 直接返回自定义HttpResponse,无需重定向 return HttpResponse("登录成功,自定义响应内容") # 若需要重定向,可自行指定: # return HttpResponseRedirect(reverse("login_success"))
注意事项
form.save()已经包含了双因素认证的验证和用户登录逻辑,确保不要遗漏这一步,否则登录状态不会生效。- 如果插件依赖已登录的用户状态,必须在
form.save()之后执行插件逻辑。
内容的提问来源于stack exchange,提问作者John Gardounis
相关产品推荐
相关产品推荐

