django-rest-framework - 自定义身份验证后端冲突默认后端
问题描述
我的任务有 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
视图.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
设置.py:
AUTHENTICATION_BACKENDS = (
'accounts.auth_backends.PasswordlessAuthBackend',
"django.contrib.auth.backends.ModelBackend",
)
解决方案
您似乎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.backend
您设置,login()
它将读取。您无需在通话中手动设置。
推荐阅读
- php - 如何使用php为程序制作快捷方式
- php - 将具有 maxlength 的自定义字段添加到 WooCommerce 结帐页面
- angular - 您可以在 Angular / NestJS 模块提供程序中使用 `useFactory` 属性并返回一个类而不是实例吗?
- c# - C# - 如果字符串以相同的数字开头和结尾,我如何为字符串着色
- reactjs - 尝试安装依赖项时,npm 失败并显示错误代码 ETARGET
- asp.net - IIS https请求比http慢4-5倍,lsass.exe消耗40% CPU
- java - Spring Boot 每月测试@Scheduled
- amazon-s3 - 如何将 .wav 文件目录添加到 Kedro 数据目录?
- json - 有没有办法在 JSON_TABLE 的 COLUMNS 子句中使用 NVARCHAR2 数据类型?
- activemq-artemis - 带有 HTTPS 的 ActiveMQ Artemis 管理控制台