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

请问这种生成Access Token的方案是否可行?

该Access Token生成方案是否可行?

你的方案技术上可以运行,但存在严重的安全和设计缺陷,不建议直接使用,具体分析和改进建议如下:


你的现有流程回顾

1. 生成随机密码

b := make([]byte, length)
if _, err := rand.Read(b); err != nil {
   return "", err
}

return hex.EncodeToString(b), nil

2. 生成Access Token并存储

const (
    timeCost    = 1
    memoryCost  = 64 * 1024
    parallelism = 4
    keyLength   = 20
    saltLength  = 12
)

saltRaw := make([]byte, saltLength)
if _, err := rand.Read(saltRaw); err != nil {
    return "", err
}
salt := base64.URLEncoding.EncodeToString(saltRaw)

hash := argon2.IDKey([]byte(password), []byte(salt), timeCost, memoryCost, parallelism, keyLength)
encodedHash := base64.URLEncoding.EncodeToString(hash)
  • 将encodedHash存入数据库
  • 返回给用户的Token格式:password.salt.timeCost.memoryCost.parallelism

3. 验证流程

  • 按.拆分Token提取各字段
  • 重新生成Argon2哈希
  • 查询数据库验证哈希是否存在

核心问题分析

  1. Token直接暴露敏感验证因子
    返回给用户的Token包含了未加密的原始随机password,相当于把验证所需的核心明文信息直接交给了用户。一旦Token泄露,攻击者不需要破解哈希,直接就能用泄露的Token通过验证——Argon2哈希的防破解能力完全被浪费。

  2. 缺乏Token生命周期管理
    数据库只存储哈希值,没有关联用户ID、过期时间、吊销状态等信息:

    • 无法区分不同用户的Token,理论上存在哈希碰撞导致的错误验证
    • 生成的Token永久有效,一旦泄露无法主动吊销,只能全量重置
  3. Argon2的使用场景错位
    Argon2是为低熵的用户密码设计的慢哈希算法(通过高计算/内存成本抵御暴力破解),但你的随机password本身是高熵值,用Argon2属于性能浪费,换成HMAC-SHA256这类快速哈希足够安全。


改进后的可行方案

核心思路

  • 不向用户暴露任何验证用的明文因子,只返回高熵随机Token字符串
  • 服务器端存储Token的哈希、关联用户信息及生命周期
  • 验证时通过哈希匹配+状态检查完成校验

示例代码

生成Token

import (
    "crypto/hmac"
    "crypto/rand"
    "crypto/sha256"
    "encoding/base64"
    "encoding/hex"
    "time"
)

// 服务器端保密的密钥,用于生成Token哈希
var serverSecret = []byte("your-strong-server-secret")

func GenerateToken(userID int) (string, error) {
    // 生成32字节高熵随机Token
    tokenRaw := make([]byte, 32)
    if _, err := rand.Read(tokenRaw); err != nil {
        return "", err
    }
    token := base64.URLEncoding.EncodeToString(tokenRaw)

    // 生成Token的HMAC哈希用于存储
    h := hmac.New(sha256.New, serverSecret)
    h.Write([]byte(token))
    tokenHash := hex.EncodeToString(h.Sum(nil))

    // 将哈希、用户ID、过期时间存入数据库
    // 示例SQL:INSERT INTO tokens (hash, user_id, expires_at) VALUES (?, ?, ?)
    _, err := db.Exec("INSERT INTO tokens (hash, user_id, expires_at) VALUES (?, ?, ?)",
        tokenHash, userID, time.Now().Add(24*time.Hour))
    if err != nil {
        return "", err
    }

    // 返回给用户的只有随机Token字符串
    return token, nil
}

验证Token

func ValidateToken(submittedToken string) (int, error) {
    // 生成提交Token的HMAC哈希
    h := hmac.New(sha256.New, serverSecret)
    h.Write([]byte(submittedToken))
    submittedHash := hex.EncodeToString(h.Sum(nil))

    // 查询数据库,检查哈希存在且未过期
    var userID int
    var expiresAt time.Time
    err := db.QueryRow("SELECT user_id, expires_at FROM tokens WHERE hash = ? AND expires_at > ?",
        submittedHash, time.Now()).Scan(&userID, &expiresAt)
    if err != nil {
        return 0, err
    }

    return userID, nil
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 17:17:44