自定义身份验证后端冲突默认后端
custom authentication backends conflict default backend
我的任务有 2 个视图
1.接受phone号和密码认证登录用户
2。接受 phone 没有密码的数字和令牌,以执行我创建的自定义后端,其中身份验证没有密码
当我在设置的 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,},
serializers.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",
)
您的 PasswordlessAuthBackend
用户登录似乎没有检查 password/token。
Django 检查您后端的参数名称以确定它是否可以被调用。尝试为每个用例制作一个后端,仅使用 该身份验证所需的参数(例如 phone_number、令牌)
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.backend
,login()
将读取。调用时无需手动设置。
我的任务有 2 个视图 1.接受phone号和密码认证登录用户
2。接受 phone 没有密码的数字和令牌,以执行我创建的自定义后端,其中身份验证没有密码
当我在设置的 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,},
serializers.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",
)
您的 PasswordlessAuthBackend
用户登录似乎没有检查 password/token。
Django 检查您后端的参数名称以确定它是否可以被调用。尝试为每个用例制作一个后端,仅使用 该身份验证所需的参数(例如 phone_number、令牌)
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.backend
,login()
将读取。调用时无需手动设置。