django 使用phone_number和password(而非用户名和口令)自定义JWT身份验证

um6iljoc  于 2022-12-05  发布在  Go
关注(0)|答案(2)|浏览(168)

我已经使用链接https://django-rest-framework-simplejwt.readthedocs.io/en/latest/index.html在我的项目中实现了JWT身份验证和授权
代码运行正常,但我需要将“username”和“password”更改为“移动的_number”和“otp”。
我有一个自定义用户模型,如

class User(AbstractUser):
  password = models.CharField(max_length=128, blank=True, null=True)
  email = models.EmailField(max_length=254, unique=True)
  dial_code_id = models.CharField(max_length=100)
  mobile_number = models.CharField(max_length=100, blank=True, null=True)
  username = models.CharField(max_length=150, unique=True, blank=True, null=True)
  is_resource = models.BooleanField(default=False)
  is_customer = models.BooleanField(default=False)
  is_active = models.BooleanField(default=True)
  skills = models.ManyToManyField(Skills)

  class Meta:
      db_table = "my_user"

  def __str__(self):
      return self.mobile_number

出于登录的目的,我计划有一个OTP模型,如

class LoginOtp(models.Model):
  user = models.ForeignKey(User, on_delete=models.CASCADE)
  otp = models.IntegerField()
  created_on = models.DateTimeField(default=datetime.utcnow())

  class Meta:
    db_table = "otp"

1.我不知道以上方法是否正确,如果不正确,请指正。
1.如何将“用户名”和“密码”替换为“移动的号码”和“OTP”。

  • 谢谢-谢谢
8i9zcol2

8i9zcol21#

首先,创建一个视图来接受用户的mobile_number。验证它是否存在于您的User模型中,如果存在,则使用消息API服务(如Twilio)发送OTP。如果mobile_number不存在,则相应地通知用户。
此外,您还需要另一个端点来验证用户是否已收到OTP。这也可以使用相同的消息传递API服务Twilio来完成。一旦Twilio验证了OTP,您就可以使用这个简单的JWT来生成refreshaccess令牌,如下所示-

from rest_framework_simplejwt.tokens import RefreshToken

#generate refresh token and access token.
token = RefreshToken.for_user(user)

for_user()方法将接受User模型的示例。在您的情况下,是刚刚验证OTP的用户。
如果OTP验证成功,您可以返回如下响应-

{
   "refresh":str(token),
   "access": str(token.access_token)
}
pieyvz9o

pieyvz9o2#

@api_view(['POST'])
def add_phone(request):
    
    digits = "0123456789"
    OTP = ""
    for i in range(6) :
            OTP += digits[math.floor(random.random() * 10)]
    dataItem = request.data
    
    dataItem["otp"] = OTP
    item = PhoneNumberSerializer(data=request.data)

    # validating for already existing data
    if PhoneNumber.objects.filter(number=request.data['number']).exists():
        
        if item.is_valid():
            print("already exists")
            todo_instance=PhoneNumber.objects.get(number=request.data['number'])
            data = {'number': request.data['number'], 'verified': False,'otp': OTP }
            serializer = PhoneNumberSerializer(instance = todo_instance, data=data, partial = True)
            if serializer.is_valid():
                serializer.save()
                send_otp(OTP)
        return Response(data, status=status.HTTP_200_OK) 
    else:
        if item.is_valid():
            item.save()
            send_otp(OTP)
        return Response(item.data, status=status.HTTP_200_OK)    
    
    
    
    
    
@api_view(['POST'])
def verify_phone(request):
    if PhoneNumber.objects.filter(number=request.data['number']).exists():
        user = get_object_or_404(PhoneNumber, **dict(number=request.data['number']))
        user_serializer = PhoneNumberSerializer(user)
        token = RefreshToken.for_user(user)
        if user_serializer['otp'].value==request.data['otp']:
            data = {'number': request.data['number'], 'otp': request.data['otp'],'verified': True }
            serializer = PhoneNumberSerializer(instance = user, data=data, partial = True)
            if serializer.is_valid():
                serializer.save()
                
                
            return Response({
   "refresh":str(token),
   "access": str(token.access_token),
   "data": data
}, status=status.HTTP_200_OK) 
        else:
          return Response(dict(detail='Invalid Opt'),status=200)    
    else:
        pass
    return Response(dict(detail='The provided code did not match or has expired'),status=200)

相关问题