如何在django-rest-framework-simplejwt中使用phone number与otp替代username和password生成Token并配置自定义字段
如何用手机号+验证码替换默认字段生成JWT Token(django-rest-framework-simplejwt)
没问题,我来一步步教你实现这个需求——用phone_number和otp替换默认的username和password来获取Token。核心思路是自定义Token获取视图和序列化器,替换simplejwt默认的验证逻辑。
步骤1:自定义Token序列化器和视图
首先在你的api_views.py里添加以下代码,我们要重写默认的序列化器,把验证逻辑改成手机号+验证码:
from rest_framework_simplejwt.views import TokenObtainPairView from rest_framework_simplejwt.serializers import TokenObtainPairSerializer from rest_framework import serializers from .models import Patient # 这里替换成你实际的用户模型,比如Patient/Doctor/User class CustomTokenObtainPairSerializer(TokenObtainPairSerializer): # 告诉序列化器我们用phone_number作为身份识别字段 username_field = 'phone_number' def validate(self, attrs): # 从请求参数里获取手机号和验证码 phone_number = attrs.get('phone_number') otp = attrs.get('otp') # 第一步:检查手机号是否已注册 try: user = Patient.objects.get(phone_number=phone_number) except Patient.DoesNotExist: raise serializers.ValidationError("该手机号未注册,请先完成注册") # 第二步:验证验证码是否正确(这里要和你发送验证码的逻辑对应) # 示例1:如果存在用户模型字段 if user.otp != otp: raise serializers.ValidationError("验证码错误或已过期") # 示例2:如果用缓存存储(更推荐,避免污染用户模型) # from django.core.cache import cache # cached_otp = cache.get(f"otp_{phone_number}") # if not cached_otp or cached_otp != otp: # raise serializers.ValidationError("验证码错误或已过期") # 验证通过后,生成Token # 这里调用父类的方法,用手机号作为username,传一个占位符密码(因为我们已经跳过密码验证) data = super().validate({'username': phone_number, 'password': 'dummy_value'}) # 可选:验证成功后清除验证码,防止重复使用 user.otp = None # 如果存在用户模型字段 user.save() # cache.delete(f"otp_{phone_number}") # 如果用缓存存储 return data class CustomTokenObtainPairView(TokenObtainPairView): # 指定我们自定义的序列化器 serializer_class = CustomTokenObtainPairSerializer
步骤2:修改urls.py中的登录路由
接下来把你原来的默认登录路由替换成我们自定义的视图:
# urls.py from django.urls import path from . import views from . import api_views from django.conf.urls.static import static from django.conf import settings # 导入我们自定义的视图 from .api_views import CustomTokenObtainPairView from rest_framework_simplejwt.views import TokenRefreshView urlpatterns = [ # Api Urls path('api/',api_views.getRoutes,name="api"), path('api/register',api_views.registerPatient,name="signup"), path('api/patient/',api_views.getPatients,name="patients"), path('api/create/',api_views.CreatePatient,name="create"), path('api/patient/<str:pk>/',api_views.getPatient,name="patient"), path('api/update/<str:pk>/',api_views.updatePatient,name="update"), path('api/delete/<str:pk>/',api_views.deletePatient,name="delete"), # 替换原来的TokenObtainPairView为自定义视图 path('api/login/', CustomTokenObtainPairView.as_view(), name='token_obtain_pair'), path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'), path('api/doctor/',api_views.doctorRegister,name="doctorreg"), path('api/getroutes/', api_views.getRoutes, name='getroutes'), path('api/sotp/',api_views.send_otp,name="sotp"), path('api/votp/',api_views.verify_otp,name="votp"), path('api/signup/',api_views.registerPatient,name="signup"), ]
注意事项
- 确保你的用户模型(比如
Patient)有phone_number字段,并且发送验证码时正确存储了OTP(推荐用Django缓存存储,设置合理的过期时间,比如5分钟) - 验证成功后一定要清除OTP,避免被重复使用
- 如果你的用户模型不是默认的
User,要确保在settings.py里配置了AUTH_USER_MODEL指向你的自定义模型
内容的提问来源于stack exchange,提问作者Robust IIT
相关产品推荐
相关产品推荐

