django rest框架中的多用户身份验证
multiple user authentication in django rest framework
我的代码
models.py
class User(AbstractUser):
username = None
email = models.EmailField(_('email address'), unique=True)
phone_no = models.CharField(unique=True, null=True,max_length=10)
is_verified = models.BooleanField(default=False)
# type_choice = (
# ('photographer', 'Photographer'),
# ('customer','Customer'),
# )
is_customer = models.BooleanField(default=False)
is_photographer = models.BooleanField(default=False)
#user_type = models.CharField(choices = type_choice,max_length=20,default="customer")
auth_provider = models.CharField(max_length=255, blank=False, null=False, default=AUTH_PROVIDERS.get('email'))
USERNAME_FIELD = 'email'
objects = CustomUserManager()
REQUIRED_FIELDS = []
def __str__(self):
return self.email
def tokens(self):
refresh = RefreshToken.for_user(self)
return {
'refresh': str(refresh),
'access': str(refresh.access_token)
}
serializer.py
class UserSerializers(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'first_name','last_name','phone_no','email','password','is_photographer',
'is_customer']
extra_kwargs = {
'password' :{'write_only':True} # to does not return password in api ## postman
}
# convert password to hash key
def create(self, validated_data):
password = validated_data.pop('password',None)
instance = self.Meta.model(**validated_data)
if password is not None:
instance.set_password(password)
if len(password) <6:
raise serializers.ValidationError("entre strong password")
instance.save()
return instance
# login serializers
class UserLoginSerializer(serializers.ModelSerializer):
email = serializers.EmailField(max_length=255, min_length=3)
password = serializers.CharField(max_length=68, min_length=6, write_only=True)
tokens = serializers.SerializerMethodField()
def get_tokens(self, obj):
user = User.objects.get(email=obj['email'])
return {
'refresh': user.tokens()['refresh'],
'access': user.tokens()['access']
}
class Meta:
model = User
fields = ['email', 'password', 'tokens']
def validate(self, attrs):
email = attrs.get('email', '')
password = attrs.get('password', '')
filtered_user_by_email = User.objects.filter(email=email)
user = auth.authenticate(email=email, password=password)
if filtered_user_by_email.exists() and filtered_user_by_email[0].auth_provider != 'email':
raise AuthenticationFailed(
detail='Please continue your login using ' + filtered_user_by_email[0].auth_provider)
if not user:
raise AuthenticationFailed('Invalid credentials, try again')
if not user.is_active:
raise AuthenticationFailed('Account disabled, contact admin')
if not user.is_verified:
raise AuthenticationFailed('Email is not verified')
return {
'email': user.email,
'tokens': user.tokens,
}
return super().validate(attrs)
views.py
class Register(generics.GenericAPIView):
permission_classes = [AllowAny]
serializer_class = UserSerializers
# renderer_classes = (UserRenderer,)
def post(self, request):
user = request.data
serializer = self.serializer_class(data=user)
serializer.is_valid(raise_exception=True)
serializer.save()
user_data = serializer.data
user = User.objects.get(email=user_data['email'])
token = RefreshToken.for_user(user).access_token
current_site = get_current_site(request).domain
relativeLink = reverse('email-verify')
absurl = 'http://'+current_site+relativeLink+"?token="+str(token)
email_body = 'Hi '+user.email + \
' Use the link below to verify your email \n' + absurl
data = {'email_body': email_body, 'to_email': user.email,
'email_subject': 'Verify your email'}
Utils.send_email(data)
return Response(user_data, status=status.HTTP_201_CREATED)
# verify the mail that send in the mail box
class VerifyEmail(views.APIView):
permission_classes = [AllowAny]
serializer_class = EmailVerificationSerializer
def get(self, request):
token = request.GET.get('token')
try:
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"],type=jwt)
user = User.objects.get(id=payload['user_id'])
if not user.is_verified:
user.is_verified = True
user.save()
return Response({'email': 'Successfully activated'}, status=status.HTTP_200_OK)
except jwt.ExpiredSignatureError as identifier:
return Response({'error': 'Activation Expired'}, status=status.HTTP_400_BAD_REQUEST)
except jwt.exceptions.DecodeError as identifier:
return Response({'error': 'Invalid token'}, status=status.HTTP_400_BAD_REQUEST)
# login apis
class Login(generics.GenericAPIView):
permission_classes = [AllowAny]
serializer_class = UserLoginSerializer
def post(self, request):
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
return Response(serializer.data, status=status.HTTP_200_OK)
我想在 django rest 框架中进行多重身份验证,我完成了注册,但在登录用户时遇到问题,我收到了电子邮件、刷新令牌和访问令牌,但我没有获得用户类型。
当我登录时,它应该验证它的客户或摄影师,它还应该 return 类型的用户,所以它有助于 forntens。
请帮助登录用户 is_customer 或 is_photographer。
您没有在登录序列化程序中包含 is_customer
和 is_photographer
字段,因此不会返回。
# serializers.py
class UserLoginSerializer(serializers.ModelSerializer):
# ....
is_customer = serializers.BooleanField(read_only=True)
is_photographer = serializers.BooleanField(read_only=True)
class Meta:
fields = ['email', 'password', 'tokens', 'is_customer', 'is_photographer']
我的代码
models.py
class User(AbstractUser):
username = None
email = models.EmailField(_('email address'), unique=True)
phone_no = models.CharField(unique=True, null=True,max_length=10)
is_verified = models.BooleanField(default=False)
# type_choice = (
# ('photographer', 'Photographer'),
# ('customer','Customer'),
# )
is_customer = models.BooleanField(default=False)
is_photographer = models.BooleanField(default=False)
#user_type = models.CharField(choices = type_choice,max_length=20,default="customer")
auth_provider = models.CharField(max_length=255, blank=False, null=False, default=AUTH_PROVIDERS.get('email'))
USERNAME_FIELD = 'email'
objects = CustomUserManager()
REQUIRED_FIELDS = []
def __str__(self):
return self.email
def tokens(self):
refresh = RefreshToken.for_user(self)
return {
'refresh': str(refresh),
'access': str(refresh.access_token)
}
serializer.py
class UserSerializers(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'first_name','last_name','phone_no','email','password','is_photographer',
'is_customer']
extra_kwargs = {
'password' :{'write_only':True} # to does not return password in api ## postman
}
# convert password to hash key
def create(self, validated_data):
password = validated_data.pop('password',None)
instance = self.Meta.model(**validated_data)
if password is not None:
instance.set_password(password)
if len(password) <6:
raise serializers.ValidationError("entre strong password")
instance.save()
return instance
# login serializers
class UserLoginSerializer(serializers.ModelSerializer):
email = serializers.EmailField(max_length=255, min_length=3)
password = serializers.CharField(max_length=68, min_length=6, write_only=True)
tokens = serializers.SerializerMethodField()
def get_tokens(self, obj):
user = User.objects.get(email=obj['email'])
return {
'refresh': user.tokens()['refresh'],
'access': user.tokens()['access']
}
class Meta:
model = User
fields = ['email', 'password', 'tokens']
def validate(self, attrs):
email = attrs.get('email', '')
password = attrs.get('password', '')
filtered_user_by_email = User.objects.filter(email=email)
user = auth.authenticate(email=email, password=password)
if filtered_user_by_email.exists() and filtered_user_by_email[0].auth_provider != 'email':
raise AuthenticationFailed(
detail='Please continue your login using ' + filtered_user_by_email[0].auth_provider)
if not user:
raise AuthenticationFailed('Invalid credentials, try again')
if not user.is_active:
raise AuthenticationFailed('Account disabled, contact admin')
if not user.is_verified:
raise AuthenticationFailed('Email is not verified')
return {
'email': user.email,
'tokens': user.tokens,
}
return super().validate(attrs)
views.py
class Register(generics.GenericAPIView):
permission_classes = [AllowAny]
serializer_class = UserSerializers
# renderer_classes = (UserRenderer,)
def post(self, request):
user = request.data
serializer = self.serializer_class(data=user)
serializer.is_valid(raise_exception=True)
serializer.save()
user_data = serializer.data
user = User.objects.get(email=user_data['email'])
token = RefreshToken.for_user(user).access_token
current_site = get_current_site(request).domain
relativeLink = reverse('email-verify')
absurl = 'http://'+current_site+relativeLink+"?token="+str(token)
email_body = 'Hi '+user.email + \
' Use the link below to verify your email \n' + absurl
data = {'email_body': email_body, 'to_email': user.email,
'email_subject': 'Verify your email'}
Utils.send_email(data)
return Response(user_data, status=status.HTTP_201_CREATED)
# verify the mail that send in the mail box
class VerifyEmail(views.APIView):
permission_classes = [AllowAny]
serializer_class = EmailVerificationSerializer
def get(self, request):
token = request.GET.get('token')
try:
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"],type=jwt)
user = User.objects.get(id=payload['user_id'])
if not user.is_verified:
user.is_verified = True
user.save()
return Response({'email': 'Successfully activated'}, status=status.HTTP_200_OK)
except jwt.ExpiredSignatureError as identifier:
return Response({'error': 'Activation Expired'}, status=status.HTTP_400_BAD_REQUEST)
except jwt.exceptions.DecodeError as identifier:
return Response({'error': 'Invalid token'}, status=status.HTTP_400_BAD_REQUEST)
# login apis
class Login(generics.GenericAPIView):
permission_classes = [AllowAny]
serializer_class = UserLoginSerializer
def post(self, request):
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
return Response(serializer.data, status=status.HTTP_200_OK)
我想在 django rest 框架中进行多重身份验证,我完成了注册,但在登录用户时遇到问题,我收到了电子邮件、刷新令牌和访问令牌,但我没有获得用户类型。 当我登录时,它应该验证它的客户或摄影师,它还应该 return 类型的用户,所以它有助于 forntens。 请帮助登录用户 is_customer 或 is_photographer。
您没有在登录序列化程序中包含 is_customer
和 is_photographer
字段,因此不会返回。
# serializers.py
class UserLoginSerializer(serializers.ModelSerializer):
# ....
is_customer = serializers.BooleanField(read_only=True)
is_photographer = serializers.BooleanField(read_only=True)
class Meta:
fields = ['email', 'password', 'tokens', 'is_customer', 'is_photographer']