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

Django用户密码哈希算法定制:外部数据库SHA512密码迁移后认证失败问题求助

问题排查与解决方案

你的自定义密码哈希器存在几个关键问题导致认证失败,我来逐一拆解并给出修正方案:

核心问题分析

  1. encode方法返回类型错误:你返回的是hashlib.sha512对象,而非数据库存储的十六进制字符串,导致验证时无法和数据库中的密码字符串做有效对比。
  2. verify方法逻辑错误:你直接用encode返回的hash对象和数据库中的字符串进行比较,类型不匹配必然失败。
  3. 未兼容Django密码格式:Django的密码存储遵循algorithm$salt$hash的格式,而你迁移的密码是纯SHA512十六进制字符串,需要兼容这种场景。

修正后的自定义哈希器代码

import hashlib
from django.contrib.auth.hashers import BasePasswordHasher, mask_hash
from django.utils.crypto import constant_time_compare
from django.utils.translation import gettext_noop as _

class CustomPasswordHasher(BasePasswordHasher):
    algorithm = 'sha512'

    def salt(self):
        # 原密码无salt,返回空字符串
        return ''

    def encode(self, password, salt):
        # 计算密码的SHA512十六进制摘要
        hash_hex = hashlib.sha512(password.encode()).hexdigest()
        # 遵循Django密码格式:algorithm$salt$hash
        return f"{self.algorithm}${salt}${hash_hex}"

    def verify(self, password, encoded):
        # 兼容两种密码格式:迁移的纯哈希字符串 / Django格式字符串
        if '$' in encoded:
            # 拆分Django格式的密码段
            algorithm, salt, hash_hex = encoded.split('$', 2)
            # 如果算法不匹配,直接返回验证失败
            if algorithm != self.algorithm:
                return False
        else:
            # 处理迁移过来的纯SHA512哈希字符串
            salt = ''
            hash_hex = encoded

        # 计算输入密码的SHA512哈希
        computed_hash = hashlib.sha512(password.encode()).hexdigest()
        # 用constant_time_compare防止时序攻击
        return constant_time_compare(hash_hex, computed_hash)

    def safe_summary(self, encoded):
        # 适配两种格式的密码摘要展示
        if '$' in encoded:
            algorithm, salt, hash_hex = encoded.split('$', 2)
        else:
            algorithm = self.algorithm
            salt = ''
            hash_hex = encoded

        return {
            _('algorithm'): algorithm,
            _('salt'): mask_hash(salt, show=0),  # 无salt,隐藏全部
            _('hash'): mask_hash(hash_hex, show=6),  # 显示前6位哈希
        }

    def must_update(self, encoded):
        # 建议:验证通过后自动升级为更安全的哈希算法(如PBKDF2)
        return '$' not in encoded

额外优化建议

  1. 自动升级密码哈希:上面的must_update方法会标记迁移过来的纯哈希密码为需要更新,当用户成功登录后,Django会自动使用PASSWORD_HASHERS列表中后续的更安全哈希器(比如PBKDF2)重新加密密码并保存到数据库,提升安全性。
  2. 测试验证:你可以创建一个测试用户,将其password字段直接设置为你提供的示例哈希值,然后尝试登录,验证是否能成功认证。

配置确认

你的settings.py中PASSWORD_HASHERS的配置是正确的,确保CustomPasswordHasher排在最前面,这样Django会优先使用它来验证密码。

内容的提问来源于stack exchange,提问作者I. Simonov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 06:57:45