如何配置仅通过手机号而非用户名密码获取SimpleJWT令牌?
仅通过手机号获取SimpleJWT访问令牌的解决方案
要实现仅用手机号生成JWT令牌,你需要正确重写TokenObtainPairSerializer和对应的视图,同时确保用户模型适配无密码场景。以下是具体步骤:
1. 适配无密码的用户模型(可选但推荐)
如果你的用户体系不需要密码,先自定义用户模型,将手机号设为唯一标识并禁用密码验证:
from django.contrib.auth.models import AbstractUser, BaseUserManager from django.db import models class CustomUserManager(BaseUserManager): def create_user(self, mobile, **extra_fields): if not mobile: raise ValueError("手机号不能为空") user = self.model(mobile=mobile, **extra_fields) # 设置不可用密码,避免密码校验 user.set_unusable_password() user.save(using=self._db) return user def create_superuser(self, mobile, password=None, **extra_fields): extra_fields.setdefault('is_staff', True) extra_fields.setdefault('is_superuser', True) return self.create_user(mobile, password=password, **extra_fields) class CustomUser(AbstractUser): username = None mobile = models.CharField(max_length=11, unique=True) # 将手机号设为用户唯一标识字段 USERNAME_FIELD = 'mobile' REQUIRED_FIELDS = [] objects = CustomUserManager()
2. 重写TokenObtainPairSerializer
创建自定义序列化器,仅接收手机号参数,跳过密码校验:
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer from rest_framework import serializers from django.contrib.auth import get_user_model User = get_user_model() class MobileTokenObtainPairSerializer(TokenObtainPairSerializer): # 只保留手机号作为输入字段 mobile = serializers.CharField(required=True) def validate(self, attrs): mobile = attrs.get('mobile') if not mobile: raise serializers.ValidationError("手机号不能为空") # 根据手机号查询用户 try: user = User.objects.get(mobile=mobile) except User.DoesNotExist: raise serializers.ValidationError("该手机号未注册") # 可选:验证用户状态 if not user.is_active: raise serializers.ValidationError("用户已被禁用") # 生成JWT令牌 refresh = self.get_token(user) return { 'refresh': str(refresh), 'access': str(refresh.access_token), }
3. 重写TokenObtainPairView
替换默认视图,使用自定义序列化器:
from rest_framework_simplejwt.views import TokenObtainPairView from .serializers import MobileTokenObtainPairSerializer class MobileTokenObtainPairView(TokenObtainPairView): serializer_class = MobileTokenObtainPairSerializer
4. 配置URL路由
将默认的JWT令牌路由替换为自定义视图:
from django.urls import path from .views import MobileTokenObtainPairView urlpatterns = [ path('api/token/', MobileTokenObtainPairView.as_view(), name='token_obtain_pair'), ]
常见失败原因排查
- 未正确替换视图:如果仍使用默认
TokenObtainPairView,自定义序列化器不会生效 - 用户模型配置错误:未将手机号设为
USERNAME_FIELD,或未禁用密码校验 - 序列化器逻辑错误:未正确处理用户查询或令牌生成逻辑
内容的提问来源于stack exchange,提问作者Abdulaziz Hussein
相关产品推荐
相关产品推荐

