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

使用Go生成的Django密码哈希无法在Admin后台验证

问题分析与解决方案

你的Go实现和Django的pbkdf2_sha256哈希生成逻辑存在两处核心差异,导致Django无法验证密码,甚至自动更新哈希:

核心问题点

  • Base64编码方式不匹配:Django对PBKDF2输出的哈希值使用URL-safe Base64编码,并自动移除末尾的填充符号=;你的代码使用标准Base64编码,保留了填充符号,这会导致哈希校验失败。
  • 盐的生成逻辑不一致:Django的盐是16字节随机二进制数据,经URL-safe Base64编码并去掉填充后得到22位字符串;你的代码直接生成22位字母数字字符串,字节结构和Django的盐不匹配。

修正后的Go代码

import (
    "crypto/rand"
    "crypto/sha256"
    "encoding/base64"
    "errors"
    "fmt"
    "strings"
    "golang.org/x/crypto/pbkdf2"
)

func PasswordEncode(password string, salt string, iterations int) (string, error) {
    if strings.TrimSpace(salt) == "" {
        var err error
        salt, err = CreateDjangoStyleSalt()
        if err != nil {
            return "", err
        }
    }

    if strings.Contains(salt, "$") {
        return "", errors.New("salt contains dollar sign ($)")
    }

    if iterations <= 0 {
        iterations = 390000 // 匹配Django当前默认迭代次数
    }

    hash := pbkdf2.Key([]byte(password), []byte(salt), iterations, sha256.Size, sha256.New)
    // 使用URL-safe Base64编码,去掉末尾填充
    b64Hash := strings.TrimRight(base64.URLEncoding.EncodeToString(hash), "=")

    return fmt.Sprintf("%s$%d$%s$%s", "pbkdf2_sha256", iterations, salt, b64Hash), nil
}

// 生成Django风格的盐:16字节随机二进制 → URL-safe Base64编码 → 去掉填充(得到22位字符串)
func CreateDjangoStyleSalt() (string, error) {
    saltBytes := make([]byte, 16)
    _, err := rand.Read(saltBytes)
    if err != nil {
        return "", err
    }
    // URL-safe编码并移除末尾的=
    return strings.TrimRight(base64.URLEncoding.EncodeToString(saltBytes), "="), nil
}

验证说明

  1. 用修正后的函数生成密码example的哈希,格式会和Django生成的完全一致。
  2. 登录Django Admin时,系统会正确校验哈希,不会再提示密码无效,也不会自动更新数据库中的哈希值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 18:21:35