You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将密码转换为哈希值?基于Django REST Framework的实现咨询

在Django DRF中实现密码哈希存储的方法

嘿,针对你用Django DRF开发的这个用户信息模块,要把明文密码转成安全的哈希值存储其实很简单,Django本身就自带了成熟的密码哈希工具,结合你给出的代码,我给你两种常用的靠谱方案:

方案一:重写序列化器的create/update方法(推荐)

因为你用的是ModelViewSet和ModelSerializer,直接在序列化器里处理密码哈希是最直观的,而且能完美适配DRF的请求处理流程:

首先先导入Django的密码哈希工具:

from django.contrib.auth.hashers import make_password

然后修改你的InfoSerializer:

class InfoSerializer(serializers.ModelSerializer):
    created_time = serializers.DateTimeField(required=False)
    updated_time = serializers.DateTimeField(required=False)
    
    # 关键:设置write_only=True,让密码只接收不返回,避免泄露哈希值
    password = serializers.CharField(write_only=True)

    class Meta:
        model = Info
        fields = ['username', 'email', 'password', 'created_time', 'updated_time']

    def create(self, validated_data):
        # 对前端传入的明文密码生成哈希
        validated_data['password'] = make_password(validated_data['password'])
        # 调用父类方法完成创建
        return super().create(validated_data)

    def update(self, instance, validated_data):
        # 如果更新时传入了新密码,才进行哈希处理
        if 'password' in validated_data:
            validated_data['password'] = make_password(validated_data['password'])
        # 调用父类方法完成更新
        return super().update(instance, validated_data)

为啥推荐这个方案?

  • 逻辑和序列化器绑定,符合DRF的设计思路,后续维护起来更清晰
  • 通过write_only=True直接控制密码字段的读写权限,安全性有保障
  • 区分创建和更新场景,更新时不传入密码就不会修改原密码,更灵活

方案二:在模型层自动处理(适合全局统一逻辑)

如果你想让所有保存Info模型的操作都自动处理密码哈希,不管是通过DRF还是后台管理,那可以把逻辑放在模型层:

方式A:重写模型的save方法

修改你的Info模型:

from django.contrib.auth.hashers import make_password, check_password

class Info(models.Model):
    username = custom_fields.NotEmptyCharField(max_length=100, unique=True)
    email = models.EmailField()
    password = custom_fields.NotEmptyCharField(max_length=100)

    def save(self, *args, **kwargs):
        # 只对明文密码哈希,避免重复哈希(比如更新其他字段时)
        if not self.password.startswith(('pbkdf2_sha256$', 'argon2$', 'bcrypt$')):
            self.password = make_password(self.password)
        super().save(*args, **kwargs)
    
    # 额外加个验证密码的方法,后续登录验证时直接用
    def check_password(self, raw_password):
        return check_password(raw_password, self.password)

方式B:用Django信号实现

如果你不想修改模型的save方法,也可以用pre_save信号来监听保存事件:

# 可以放在models.py里,或者单独建个signals.py文件
from django.db.models.signals import pre_save
from django.dispatch import receiver
from django.contrib.auth.hashers import make_password
from .models import Info

@receiver(pre_save, sender=Info)
def hash_password_before_save(sender, instance, **kwargs):
    # 同样只处理明文密码
    if not instance.password.startswith(('pbkdf2_sha256$', 'argon2$', 'bcrypt$')):
        instance.password = make_password(instance.password)

要是单独建了signals.py,记得在apps.py里注册:

from django.apps import AppConfig

class YourAppConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'your_app_name'

    def ready(self):
        import your_app_name.signals

重要提醒

  • 绝对不要自己写哈希算法!Django的make_password会自动用配置里的默认算法(默认是PBKDF2),还会自动加盐,安全性拉满
  • 验证密码一定要用check_password方法,它会自动识别哈希算法并验证,不用你自己处理
  • 永远别把哈希后的密码返回给前端,所以序列化器里的write_only=True一定要加上!

内容的提问来源于stack exchange,提问作者user9341676

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:39:11