如何将密码转换为哈希值?基于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
相关产品推荐
相关产品推荐

