使用Django ModelViewSet修改User模型用户密码不生效问题求助
问题根因
你当前的问题核心来自序列化器的更新逻辑缺失:
- 你仅重写了
UserSerializer的create方法,创建用户时调用了create_user会自动对明文密码做哈希存储;但ModelSerializer默认的update方法没有做密码特殊处理,会直接将传入的明文密码写入数据库。 - Django User模型的密码校验逻辑会将用户输入的密码做哈希运算后,与数据库存储的哈希值比对,明文存储的密码自然无法通过校验,因此看起来密码没有更新、或者变成了未知值。
- 密码修改后被登出Django后台是正常的安全机制:Django默认会在用户密码变更时,清空该用户所有已生效的会话,避免旧会话被恶意利用。
解决方案
修改serializers.py中的UserSerializer,重写update方法,手动处理密码的加密逻辑:
class UserSerializer(serializers.ModelSerializer): class Meta: model = User fields = ['id', 'username', 'password'] extra_kwargs = { 'password' : { 'write_only':True, 'required': True } } def create(self, validated_data): user = User.objects.create_user(**validated_data) Token.objects.create(user=user) # create token for the user return user # 新增update方法处理更新逻辑 def update(self, instance, validated_data): # 提取密码参数,不参与默认字段更新 password = validated_data.pop('password', None) # 先更新其他普通字段 instance = super().update(instance, validated_data) # 如果请求携带了密码参数,调用set_password做哈希存储 if password: instance.set_password(password) instance.save() # 可选:如果需要旧token失效,删除原有token并生成新token返回给前端 # instance.auth_token.delete() # Token.objects.create(user=instance) return instance
额外注意事项
- PUT请求为全量更新,需要携带所有必填字段(比如
username),如果只需要修改密码,建议使用PATCH请求做部分更新。 - 检查请求头的
Authorization拼写是否正确,部分框架对英式拼写Authorisation兼容不好,可能导致认证失败。 - 生产环境建议单独做密码修改接口,增加旧密码校验逻辑,避免越权修改密码的风险。
内容的提问来源于stack exchange,提问作者Himanshu Poddar
相关产品推荐
相关产品推荐

