beego项目必须用bcrypt而非md5/sha-256,因后者无盐、过快、易被暴力破解;应使用golang.org/x/crypto/bcrypt,其自动管理盐、支持恒定时间比对且兼容性好。

Beego 框架本身不内置密码哈希逻辑,beego 的 orm 和 auth 模块都不处理密码加盐与哈希——这事必须由开发者显式控制。直接用 md5、sha256 或拼接字符串再哈希,等于把用户密码裸奔交出去。
为什么不能在 Beego 中自己拼 salt + SHA-256?
常见错误是:手动生成 salt 字段存数据库,再写个 hash(salt + password)。这看似“加盐了”,实则漏洞明显:
- SHA-256 是快速哈希,GPU 一秒钟能跑上亿次,彩虹表+暴力破解毫无压力
- 盐值长度不够(比如只用 8 字节)、没用
crypto/rand而用math/rand,导致盐可预测 - 验证时用
==比较哈希字符串,存在时序攻击风险 - 没把算法参数、盐、哈希值打包成单字符串存储,后续升级或迁移几乎无法兼容
Beego 项目该用 bcrypt 还是 argon2?
优先选 golang.org/x/crypto/bcrypt ——它轻量、成熟、Beego 生态兼容性好,且自带盐生成和恒定时间比对。Argon2 更安全但依赖 CGO,在容器或交叉编译场景容易出问题。
实际使用只需两步:
- 注册时调用
bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost),返回完整哈希字符串(含盐、参数、结果) - 登录时调用
bcrypt.CompareHashAndPassword([]byte(storedHash), []byte(inputPassword)),内部自动提取盐并重哈希比对
注意:bcrypt.DefaultCost 默认是 10,对应约 100ms 计算耗时;若 CPU 较强,可升到 12~14,但别盲目拉高到 16 以上,否则高并发登录会阻塞。
如何在 Beego 的 Controller 中安全处理密码?
关键点不是“怎么写”,而是“在哪写”和“怎么传”。不要在前端 JS 里哈希,也不要让 Beego 的 params 直接绑定明文密码字段后不做校验就入库。
- 接收密码用
this.GetString("password"),立刻做非空和基础格式检查(如长度 ≥8),失败直接返回 400 - 哈希操作必须放在服务端逻辑里,且确保在事务提交前完成;避免先存用户再异步哈希,防止中间状态暴露明文
- 数据库字段类型设为
VARCHAR(255)(bcrypt输出最长约 60 字符,留余量防未来升级) - 切勿把
password放进struct的 ORM 标签里自动映射,应显式赋值:user.Password = hashed
遗留 MD5/SHA 存储如何平滑升级到 bcrypt?
不能一刀切改库结构或强制用户重置密码。可行路径是“懒迁移”:
- 数据库加一个
password_version字段(TINYINT,默认 0 表示旧算法) - 登录时先查该字段:若为 0,用旧方式验证;成功后立即用
bcrypt.GenerateFromPassword生成新哈希,并更新字段为 1 - 新注册用户默认走 bcrypt,
password_version设为 1 - 后续所有验证逻辑都先读
password_version再分发,避免硬编码判断哈希前缀
真正难的不是代码怎么写,而是确保每次密码变更(重置、修改)都走同一套哈希路径,且所有分支都覆盖了盐提取、恒定时间比较、错误码统一——漏掉任意一环,前面的努力就白做了。











