请问这种生成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哈希
- 查询数据库验证哈希是否存在
核心问题分析
Token直接暴露敏感验证因子
返回给用户的Token包含了未加密的原始随机password,相当于把验证所需的核心明文信息直接交给了用户。一旦Token泄露,攻击者不需要破解哈希,直接就能用泄露的Token通过验证——Argon2哈希的防破解能力完全被浪费。缺乏Token生命周期管理
数据库只存储哈希值,没有关联用户ID、过期时间、吊销状态等信息:- 无法区分不同用户的Token,理论上存在哈希碰撞导致的错误验证
- 生成的Token永久有效,一旦泄露无法主动吊销,只能全量重置
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
相关产品推荐
相关产品推荐

