【问题标题】:custom authentication backends conflict default backend自定义身份验证后端冲突默认后端
【发布时间】:2019-09-19 18:03:56
【问题描述】:

我的任务中有 2 个视图 1. 接受手机号和密码验证登录用户

2 。接受没有密码的电话号码和令牌,以执行我创建的自定义后端,其中无需密码即可完成身份验证

当我在设置中的 AUTHENTICTION BACKENDS 中添加此自定义后端时,它使视图 2 登录无需密码身份验证,用户使用任何密码登录! 那么如何在设置中添加 2 个后端而不相互冲突

自定义后端

class PasswordlessAuthBackend(ModelBackend):
    """Log in to Django without providing a password."""
    # model=UserProfile
    def authenticate(self,auth_token=None, password=None,username=None,phone_number=None,):
        try:
            return UserProfile.objects.get(phone_number=phone_number)
        except UserProfile.DoesNotExist:
            return None

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

views.py:


class LoginView(APIView):
    serializer_class = LoginSerializer 
    authentication_classes = (ModelBackend,)
    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data
                                           )
        if serializer.is_valid(raise_exception=True):
            new_data = serializer.data
            user = serializer.validated_data
            login(request,user,backend="django.contrib.auth.backends.ModelBackend")
            token, created = Token.objects.get_or_create(user=user)
            return Response(
                            {'user':new_data,'token':token.key,},
                            status=status.HTTP_200_OK)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class TokenView(APIView):
    throttle_classes=()
    permission_classes = ()
    # authentication_classes = (PasswordlessAuthBackend,)
    serializer_class=TokenSerializer
    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data,
                                           context={'request': request})
        if serializer.is_valid(raise_exception=True):
            user = serializer.validated_data
            user.backend='accounts.auth_backends.PasswordlessAuthBackend'
            print(user)
            token, created = Token.objects.get_or_create(user=user)
            login(request,user,backend='accounts.auth_backends.PasswordlessAuthBackend')
            return Response({
                    'token': token.key,
                    'user_id': user.pk,},

序列化器.py

class UserProfileSerializer(serializers.ModelSerializer):
    email=serializers.EmailField(required=False)
    class Meta:
        model = UserProfile
        fields = ('first_name','last_name','country_code','phone_number','gender','birthdate','avatar','email')

    def create(self, validated_data):
        user = UserProfile.objects.create(**validated_data)
        return user

class LoginSerializer(serializers.Serializer):
    phone_number = serializers.CharField(required=True, allow_blank=False)
    password = serializers.CharField(required=True,style={'input_type': 'password'})
    def validate(self, attrs, ):
        user = authenticate(
            phone_number=attrs['phone_number'], password=attrs['password'])
        # user = self._validate_phonenumber(phonenumber, first_token)
        if user is None:
            raise serializers.ValidationError('invalid credentials provided')
        return user

class TokenSerializer(serializers.Serializer):
    phone_number = serializers.CharField(required=True, allow_blank=False)
    def validate(self, attrs,):
        user = authenticate(
            phone_number=attrs['phone_number'])

        if user is None:
            raise serializers.ValidationError('invalid credentials provided')
        self.instance = user
        return user

settings.py:

AUTHENTICATION_BACKENDS = (
        'accounts.auth_backends.PasswordlessAuthBackend',
        "django.contrib.auth.backends.ModelBackend",
)

【问题讨论】:

    标签: django-rest-framework django-authentication django-rest-auth custom-backend


    【解决方案1】:

    您的PasswordlessAuthBackend 似乎在没有检查密码/令牌的情况下让用户登录。

    Django 检查后端的参数名称以确定是否可以调用它。尝试为每个用例制作一个后端,提供该身份验证所需的参数(例如 phone_number、token)

    class CustomAuthBackend:
        def authenticate(phone_number=None, token=None):
            try:
                phone = normalize_phone(phone) # standardize to single format
                return User.objects.get(phone=phone, token=token) # or whatever
            except ObjectDoesNotExist:
                return None 
    

    序列化器和视图可以以任何方式组合,但实际上只是调用身份验证。你似乎已经在这样做了。

    • 只有在进行会话身份验证时才需要调用login
    • authenticate() 将为您设置 user.backendlogin() 将读取。您无需在调用中手动设置。

    【讨论】:

    • 没错,自定义身份验证不是真的,非常感谢
    猜你喜欢
    • 2012-12-06
    • 2018-02-24
    • 1970-01-01
    • 2021-02-06
    • 2019-05-17
    • 2015-09-08
    • 2015-07-31
    • 2019-01-23
    • 1970-01-01
    相关资源
    最近更新 更多