[英]Django login() doesn't persist after HttpResponseRedirect
I have custom Django login forms that, since upgrading from Django 1.8
to 2.2
, no longer keep user logged in after HttpResponseRedirect
.我有自定义的 Django 登录表单,自从从
Django 1.8
升级到2.2
,不再让用户在HttpResponseRedirect
之后保持登录状态。 Here's is a generalized sample of the code:这是代码的通用示例:
@render_with('users/login.html')
def login_view(request, campaign_id=None):
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
email = form.cleaned_data['email']
password = form.cleaned_data['password']
# Login user
user = authenticate(request, email=email, password=password)
if user:
if user.is_active:
login(request, user)
return HttpResponseRedirect('/redirect-user/')
I know that login()
is working properly because if I use render
instead of HttpResponseRedirect
, the user is logged in. However, I want to redirect the user to a different view after login.我知道
login()
工作正常,因为如果我使用render
而不是HttpResponseRedirect
,则用户已登录。但是,我想在登录后将用户重定向到不同的视图。 What is the best way to do this?做这个的最好方式是什么?
UPDATE更新
It appears that the culprit is my custom authenticate backend EmailOrUsernameModelBackend
.看来罪魁祸首是我的自定义身份验证后端
EmailOrUsernameModelBackend
。 Any ideas what I am doing wrong?任何想法我做错了什么?
settings.py设置.py
AUTHENTICATION_BACKENDS = (
'social_core.backends.open_id.OpenIdAuth',
'social_core.backends.google.GoogleOpenId',
'social_core.backends.facebook.FacebookOAuth2',
'social_core.backends.google.GoogleOAuth2',
'social_core.backends.linkedin.LinkedinOAuth2',
'users.backends.EmailOrUsernameModelBackend',
'django.contrib.auth.backends.ModelBackend',
)
__init__.py __init__.py
class EmailOrUsernameModelBackend(object):
supports_object_permissions = False
supports_anonymous_user = False
supports_inactive_user = False
def authenticate(self, request, email=None, password=None):
if '@' in email:
kwargs = {'email': email.lower() }
else:
kwargs = {'username__iexact': email.lower() }
try:
user = User.objects.get(**kwargs)
if user.check_password(password):
return user
except User.DoesNotExist:
return None
Also, if I change the code and logout/login again to test, it works the 1st test and fails on subsequent tests with the same user.此外,如果我再次更改代码并注销/登录进行测试,它会在第一个测试中运行,并且在使用同一用户的后续测试中失败。
Thanks to @Sayse's suggestion about middleware/backends causing the issue.感谢@Sayse 关于导致问题的中间件/后端的建议。 Removing
'users.backends.EmailOrUsernameModelBackend'
fixed the issue in the question above, but consequently broke my login after a new user registers.删除
'users.backends.EmailOrUsernameModelBackend'
修复了上述问题中的问题,但因此在新用户注册后破坏了我的登录。 In order to get both login and registration working, I switched the other of EmailOrUsernameModelBackend
and ModelBackend
:为了让登录和注册都能正常工作,我切换了另一个
EmailOrUsernameModelBackend
和ModelBackend
:
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'users.backends.EmailOrUsernameModelBackend',
)
Per Django docs :每个 Django 文档:
The order of AUTHENTICATION_BACKENDS matters, so if the same username and password is valid in multiple backends, Django will stop processing at the first positive match.
AUTHENTICATION_BACKENDS 的顺序很重要,因此如果相同的用户名和密码在多个后端有效,Django 将在第一个正匹配时停止处理。
I am still not sure what is wrong with the EmailOrUsernameModelBackend
causing it to break my login, but this did fix the issue.我仍然不确定
EmailOrUsernameModelBackend
有什么问题导致它中断我的登录,但这确实解决了问题。 If anybody has a better fix for the root cause (ie what is wrong with this backend), I will accept as the best answer.如果有人对根本原因有更好的解决方法(即这个后端有什么问题),我将接受为最佳答案。
I had the same problem, but reordering the backends in settings did not help.我遇到了同样的问题,但在设置中重新排序后端没有帮助。
login(request, user)
can take a third argument, the backend to use, eg login(request, user)
可以采用第三个参数,即要使用的后端,例如
backend = `django.contrib.auth.backends.ModelBackend'
login(request, user, backend)
If you remove django.contrib.auth.backends.ModelBackend
from settings.AUTHENTICATION_BACKENDS, inside django/contrib/auth/__init__.py -> get_user
is:如果您从 settings.AUTHENTICATION_BACKENDS 中删除
django.contrib.auth.backends.ModelBackend
,则在django/contrib/auth/__init__.py -> get_user
是:
if backend_path in settings.AUTHENTICATION_BACKENDS:
...
else:
return None
So if you specify the backend, but its not in your settings.AUTHENTICATION_BACKENDS
, your user will never authenticate.因此,如果您指定后端,但它不在您的
settings.AUTHENTICATION_BACKENDS
,您的用户将永远不会进行身份验证。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.