简体   繁体   English

Django login() 在 HttpResponseRedirect 后不存在

[英]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 :为了让登录和注册都能正常工作,我切换了另一个EmailOrUsernameModelBackendModelBackend

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM