如何仅使用密码通过Simple JWT完成身份验证?
仅通过密码实现Simple JWT身份验证的解决方案
问题分析
你当前的代码存在两个核心问题:
- 父类
TokenObtainPairSerializer默认要求username字段,仅设置username = serializers.SerializerMethodField(required=False)无法移除父类自带的必填username字段,因此系统仍会要求输入用户名。 validate方法中的逻辑错误:你将credentials["password"]替换为user.username后调用父类验证,不符合父类验证逻辑,且父类依然需要username参数。
另外你的User模型继承AbstractBaseUser但未指定USERNAME_FIELD,这会导致Django用户认证系统报错,需要补充配置。
修正后的代码实现
1. 完善User模型
添加USERNAME_FIELD指定用password作为用户唯一标识:
from django.contrib.auth.models import AbstractBaseUser from django.db import models from django.core.validators import MinLengthValidator SHIFTS = ( # 你的班次选项 ) ROLES = ( # 你的角色选项 ) class User(AbstractBaseUser): password = models.CharField('password', max_length=4, validators=[MinLengthValidator(4)], unique=True) name = models.CharField(max_length=50, blank=True) surname = models.CharField(max_length=100, blank=True) shift = models.CharField(max_length=50, choices=SHIFTS) role = models.CharField(max_length=50, choices=ROLES) work_start_time = models.DateTimeField() work_end_time = models.DateTimeField() # 指定password作为用户唯一标识字段 USERNAME_FIELD = 'password' REQUIRED_FIELDS = []
2. 重写Token序列化器
完全自定义序列化逻辑,仅保留password字段,手动生成JWT Token:
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer from rest_framework import serializers from .models import User class CustomTokenPairSerializer(TokenObtainPairSerializer): # 仅定义password字段,移除父类的username字段 password = serializers.CharField(write_only=True) def validate(self, data): password = data.get('password') if not password: raise serializers.ValidationError("密码不能为空") # 根据唯一密码查找用户 user = User.objects.filter(password=password).first() if not user: raise serializers.ValidationError("用户不存在或密码错误") # 生成JWT Token refresh = self.get_token(user) return { 'refresh': str(refresh), 'access': str(refresh.access_token), }
3. 配置视图
修正类名拼写错误后保持视图配置:
from rest_framework_simplejwt.views import TokenObtainPairView from .serializers import CustomTokenPairSerializer class CustomObtainPairView(TokenObtainPairView): serializer_class = CustomTokenPairSerializer
安全建议
当前你的User模型中密码以明文存储,存在极大安全风险,建议改为Django默认的哈希存储方式:
- 修改模型中
password字段定义:
password = models.CharField('password', max_length=128)
- 创建用户时使用
set_password方法加密:
user = User.objects.create(...) user.set_password("用户输入的密码") user.save()
- 验证密码时使用
check_password方法:
# 在序列化器的validate方法中 user = User.objects.filter(...) # 需通过其他唯一标识(如工号)查找用户 if user and user.check_password(password): # 验证通过 else: raise serializers.ValidationError("密码错误")
内容的提问来源于stack exchange,提问作者Mike D Hovhannisyan
相关产品推荐
相关产品推荐

