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

如何在Django模型及Admin中使用MySQL SHA2(256)函数存储密码?

解决方案

你无法直接让Django模型调用MySQL的SHA2()函数自动处理密码哈希,需要通过自定义逻辑实现,以下是几种简洁的实现方式:

方法1:重写模型的save方法

这是最直接的实现,在模型保存前对密码进行哈希处理,确保无论通过Admin还是其他方式创建/更新用户,密码都会被自动哈希:

import hashlib
from django.db import models

class Users(models.Model):
    username = models.CharField(max_length=30)
    password = models.CharField(max_length=128)
    status = models.IntegerField()
    valid_from = models.DateTimeField()
    valid_to  = models.DateTimeField()
    online  = models.IntegerField()
    ip = models.CharField(max_length=20)
    created  = models.DateTimeField()

    def __str__(self):
        return f'{self.username}'

    def save(self, *args, **kwargs):
        # 仅当密码为明文时进行哈希(假设明文不会刚好是64位SHA256结果)
        if len(self.password) != 64:
            self.password = hashlib.sha256(self.password.encode('utf-8')).hexdigest()
        super().save(*args, **kwargs)

方法2:使用Django信号(更灵活)

如果不想修改模型的save方法,可以用pre_save信号在实例保存前自动处理密码:

import hashlib
from django.db import models
from django.db.models.signals import pre_save
from django.dispatch import receiver

class Users(models.Model):
    username = models.CharField(max_length=30)
    password = models.CharField(max_length=128)
    status = models.IntegerField()
    valid_from = models.DateTimeField()
    valid_to  = models.DateTimeField()
    online  = models.IntegerField()
    ip = models.CharField(max_length=20)
    created  = models.DateTimeField()

    def __str__(self):
        return f'{self.username}'

@receiver(pre_save, sender=Users)
def hash_user_password(sender, instance, **kwargs):
    # 新建用户时直接哈希
    if instance.pk is None:
        instance.password = hashlib.sha256(instance.password.encode('utf-8')).hexdigest()
    else:
        # 更新用户时,仅当密码被修改才哈希
        old_user = sender.objects.get(pk=instance.pk)
        if old_user.password != instance.password:
            instance.password = hashlib.sha256(instance.password.encode('utf-8')).hexdigest()

方法3:强制使用MySQL的SHA2()函数(不推荐)

如果必须依赖MySQL的内置函数生成哈希,可以通过原生SQL查询获取哈希值,但这种方式会让代码绑定MySQL,失去跨数据库兼容性:

from django.db import models
from django.db.models import RawQuerySet

class Users(models.Model):
    username = models.CharField(max_length=30)
    password = models.CharField(max_length=128)
    status = models.IntegerField()
    valid_from = models.DateTimeField()
    valid_to  = models.DateTimeField()
    online  = models.IntegerField()
    ip = models.CharField(max_length=20)
    created  = models.DateTimeField()

    def __str__(self):
        return f'{self.username}'

    def save(self, *args, **kwargs):
        if len(self.password) != 64:
            # 调用MySQL的SHA2函数生成哈希
            hash_result = RawQuerySet(raw_query="SELECT SHA2(%s, 256) AS hashed_pwd", params=[self.password], model=Users)
            self.password = hash_result[0].hashed_pwd
        super().save(*args, **kwargs)

注意事项

  • 优先使用Python内置的hashlib实现哈希,避免依赖特定数据库,保证代码可移植性。
  • 确保password字段的max_length足够长(SHA256哈希是64个字符,你设置的128完全足够)。
  • 如果后续需要更安全的密码存储,建议改用Django自带的密码哈希系统(如PBKDF2),它会自动处理加盐和迭代哈希,比单纯的SHA256更安全。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 16:21:01