【问题标题】:Having both username and email but using email to authenticate users in django-rest-auth同时拥有用户名和电子邮件,但使用电子邮件在 django-rest-auth 中对用户进行身份验证
【发布时间】:2020-03-18 00:15:09
【问题描述】:

在大多数教程中,我看到人们使用电子邮件或用户名。我想同时拥有这两个字段,但只使用电子邮件来使用 Django-rest-auth 对用户进行身份验证,因为电子邮件将被验证并且非常重要。但用户名在我的应用中也很重要。

models.py


class UserManager(BaseUserManager):

  def _create_user(self, email, fullname, password, is_staff, is_superuser, **extra_fields):
    if not email:
        raise ValueError('Users must have an email address')
    now = timezone.now()
    email = self.normalize_email(email)
    fullname = fullname
    user = self.model(
        email=email,
        fullname=fullname,
        is_staff=is_staff, 
        is_active=True,
        is_superuser=is_superuser, 
        last_login=now,
        date_joined=now, 
        **extra_fields
    )
    user.set_password(password)
    user.save(using=self._db)
    return user

  def create_user(self, email, fullname, password, **extra_fields):
    return self._create_user(email, fullname, password, False, False, **extra_fields)

  def create_superuser(self, email, fullname, password, **extra_fields):
    user=self._create_user(email, fullname, password, True, True, **extra_fields)
    user.save(using=self._db)
    return user


class User(AbstractBaseUser, PermissionsMixin):
    username = None
    email = models.EmailField(max_length=254, unique=True)
    fullname = models.CharField(max_length=250)
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    last_login = models.DateTimeField(null=True, blank=True)
    date_joined = models.DateTimeField(auto_now_add=True)


    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['fullname']

    objects = UserManager()

    def __str__(self):
        return self.email

序列化器.py


class CustomRegisterSerializer(RegisterSerializer):
    '''
    a custom serializer that overides the default rest-auth, and for
    the user to register himself
    '''
    username = None
    email = serializers.EmailField(required=True)
    password1 = serializers.CharField(write_only=True)
    fullname = serializers.CharField(required=True)


    def get_cleaned_data(self):
        super(CustomRegisterSerializer, self).get_cleaned_data()

        return {
            'password1': self.validated_data.get('password1', ''),
            'email': self.validated_data.get('email', ''),
            'fullname': self.validated_data.get('fullname', ''),
        }

注意:我使用 Django rest auth 对用户进行身份验证

【问题讨论】:

    标签: django django-rest-framework django-rest-auth


    【解决方案1】:

    您可以使用来自ModelBackend 的您自己的身份验证后端类并覆盖authenticate 函数。

    from django.contrib.auth.backends import ModelBackend
    from django.db.models import Q
    from django.contrib.auth import get_user_model
    
    
    class EmailAndUsernameBackend(ModelBackend):
        def authenticate(self, request, username=None, password=None, **kwargs):
            UserModel = get_user_model()
    
            if username is None:
                username = kwargs.get(UserModel.USERNAME_FIELD)
            try:
                user = UserModel.objects.get(Q(email=username) | Q(username=username))
            except UserModel.DoesNotExist:
                UserModel().set_password(password)
            else:
                if user.check_password(password) and self.user_can_authenticate(user):
                    return user
    

    你应该在settings.py AUTHENTICATION_BACKENDS 中添加(或替换为 django.contrib.auth.backends.ModelBackend)

    例如:

    AUTHENTICATION_BACKENDS = [
        ...
        'users.backends.EmailBackend',
    ]
    

    注意:如果您有其他身份验证后端,例如 OAuth 或社交登录,您应该将您的后端添加到列表末尾。

    【讨论】:

    • 所以如果我明白你在说什么,我至少需要采取 2 个步骤
    • 首先这就是我的 AUTHENTICATION_BACKENDS 的样子 ``` AUTHENTICATION_BACKENDS = ( 'django.contrib.auth.backends.ModelBackend', 'allauth.account.auth_backends.AuthenticationBackend', ) ```跨度>
    • 1) 你说我应该添加你指定的 EmailAndUsernameBackend(ModelBackend),2) 我应该替换 'django.contrib.auth.backends.ModelBackend',我猜是自定义的已指定,3)我是否还必须对我的 models.py 做任何事情?
    • 1) 正确。 2)是的,用那个替换它,但首先添加`'allauth.account.auth_backends.AuthenticationBackend'` 3)不,据我所知。
    • 最后是“EmailAndUsernameBackend(ModelBackend)”,是不是只在根目录下创建一个文件?
    猜你喜欢
    • 1970-01-01
    • 2015-03-13
    • 1970-01-01
    • 2020-02-21
    • 2020-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-20
    相关资源
    最近更新 更多