DRF 简单 jwt 从用户实例获取身份验证令牌或更改用户名和密码组合

Posted

技术标签:

【中文标题】DRF 简单 jwt 从用户实例获取身份验证令牌或更改用户名和密码组合【英文标题】:DRF simple jwt getting auth token from a user instance OR change username and password combination 【发布时间】:2021-02-25 07:51:12 【问题描述】:

我有一个聊天应用程序,它使用与 WhatsApp 相同的身份验证方法。

通常我会通过以下方式获得 jwt 身份验证令牌:

from rest_framework_simplejwt.views import TokenObtainView
path('api/token/', TokenObtainView.as_view(), name='token_obtain_pair'),

但是,当我的用户模型使用 phone_number 和验证码时,这会要求提供用户名和密码。有什么办法可以改变吗?

用户名 ======> 电话号码 密码 ======> phone_code(验证码)

第二种方式 是传递用户实例并以某种方式从中获取身份验证令牌

我的登录视图

@api_view(['POST',])
def loginuser(request):
    if request.method == 'POST':
        phone_number = request.data.get('phone_number')
        try:
            user = User.objects.get(phone_number=phone_number)
            if int(request.data.get('phone_code')) == user.phone_code and user.phone_code:
                # user.phone_code = None
                # user.save()
                return Response('phone_number': phone_number, status.HTTP_200_OK)

            else:
                return Response('error': "Invalid code", status.HTTP_400_BAD_REQUEST)
        except Exception as error:
                return Response('error': error, status.HTTP_500_INTERNAL_SERVER_ERROR)

我的用户模型:

class User(AbstractUser):
    phone_number = PhoneNumberField(unique=True)
    username = models.CharField(max_length=30)
    password = models.CharField(null=True, blank=True, max_length=20)
    about = models.CharField(
        max_length=190, default="Hi, I use Orgachat!", blank=True, null=True)
    ...
    phone_code = models.IntegerField(blank=True, null=True)    
    USERNAME_FIELD = 'phone_number'
    

    def __str__(self):
        return str(self.username)

# Save auth token, I know this should be in signals.py but whatever    
@receiver(post_save, sender=User)
def create_auth_token(sender, instance=None, created=False, **kwargs):
    if created:
        Token.objects.create(user=instance)

【问题讨论】:

【参考方案1】:
from rest_framework_simplejwt.tokens import RefreshToken, SlidingToken, UntypedToken
from django.conrtib.auth.models import User

user = User.objects.first()
SlidingToken.for_user(user)
RefreshToken.for_user(user)
str(RefreshToken.for_user(user))
str(RefreshToken.for_user(user).access_token)

您可以使用它从用户实例中获取用户 jwt 令牌。希望这对你有用。

【讨论】:

【参考方案2】:

我认为最好编写自定义后端类并将其添加到 Django,这是为了允许不同的身份验证方式,see

此外,您可以从 TokenObtainView 继承并在那里添加您的逻辑并使用此自定义类,但我更喜欢将第一个选项与 JWT 集成,因此您需要阅读文档并了解它是如何工作的。

我刚刚意识到有django-rest-framework-jwt 标签,你应该放弃使用这个包,因为它是unmaintained,改用django-rest-framework-simplejwt

【讨论】:

以上是关于DRF 简单 jwt 从用户实例获取身份验证令牌或更改用户名和密码组合的主要内容,如果未能解决你的问题,请参考以下文章

如何在 DRF 中使用身份服务器 4 验证 JWT 令牌?

如何从.Net Core API 中的身份验证 JWT 令牌中获取身份用户?

在 Django (DRF) 中使用外部 API 进行基于令牌的身份验证

身份验证后请求其他服务时如何从 JWT 令牌获取用户名?

从 Django Rest Framework 中的令牌获取经过身份验证的用户

从 Symfony3 中经过身份验证的用户 (HWIOAuth) 获取 Angular2 中的 JWT 令牌