【问题标题】:Custom authentication backend. Django自定义身份验证后端。姜戈
【发布时间】:2024-05-22 04:55:02
【问题描述】:

我想创建一个身份验证后端,允许用户仅使用他们的电子邮件(无用户名,无密码)登录。

这是我尝试过的。

后端.py:

from django.conf import settings
from django.contrib.auth.models import User

class EmailAuthBackend(object):    
    def authenticate(self, username=None, password=None):
        try:
            user = User.objects.get(email=username)
            if user:
                return user
        except User.DoesNotExist:
            return None 

settings.py:

  AUTHENTICATION_BACKENDS = (
       'path_to.backends.EmailAuthBackend',
       'django.contrib.auth.backends.ModelBackend',
      )

html:

   <form  method="post" action="{% url myproject.views.test %}">
    {% csrf_token %}

        <input type="text" name="email" value=""/>

    <button type="submit">Valider</button>

    </form>

查看:

 def test(request):
    email = ''
    if 'email' in request.POST:
        email = request.POST.get('email')
        if not User.objects.filter(email=email):
            User.objects.create(email=email)
        user = authenticate(username=email)
        if user is not None:
            if user.is_active:
                auth_login(request, user)
    return HttpResponseRedirect(reverse('home'))

它不起作用,用户未通过身份验证。当我转到 /admin 时,我也遇到了这个错误:

    AttributeError at /admin/logout/
    'EmailAuthBackend' object has no attribute 'get_user'

【问题讨论】:

    标签: django


    【解决方案1】:

    对于 Django 中的每个自定义后端,您需要指定 get_user 函数。见the documentationget_user 实现可以简单地使用现有的用户表,就像你一样:

    def get_user(self, user_id):
       try:
          return User.objects.get(pk=user_id)
       except User.DoesNotExist:
          return None
    

    这是必需的原因是您需要通过其主键从不同来源获取用户的情况。

    【讨论】:

      【解决方案2】:

      虽然Bartekanswer 是正确的,但我将提供一个示例,说明通过继承ModelBackend 来解决问题的另一种方法。

      from django.contrib.auth.backends import ModelBackend
      
      class EmailAuthBackend(ModelBackend):
          def authenticate(self, username=None, password=None, **kwargs):
              try:
                  user = User.objects.get(email=username)
                  if user.check_password(password):
                      return user
              except ObjectDoesNotExist:
                  # Run the default password hasher once to reduce the timing
                  # difference between an existing and a non-existing user (#20760).
                  User().set_password(password)
      

      get_user 已经由ModelBackend 实现,并且您将获得权限方法。

      【讨论】: