bcrypt 不是 Beego 内置模块,需手动集成 golang.org/x/crypto/bcrypt;注册时须显式哈希明文密码并转 string 存入 VARCHAR(255) 字段,登录时严格按顺序调用 CompareHashAndPassword 比对。

bcrypt 不是 Beego 框架内置的密码处理模块,它属于 Go 生态通用密码安全库 golang.org/x/crypto/bcrypt。Beego 本身不封装或干预密码哈希逻辑,你得自己集成——但好处是完全可控,且能避开框架抽象层带来的隐性坑。
注册时用 bcrypt.GenerateFromPassword 生成哈希,别碰 Beego 的 orm.Save 或自动填充
Beego 的 orm.Insert 或结构体自动绑定(如 ctx.Input.Bind)不会帮你做密码预处理。如果你把明文密码直接塞进 User.Password 字段再调用 orm.Insert,那存进去的就是明文。
必须手动拦截、校验、哈希、再写入:
- 先对原始输入做
strings.TrimSpace(),再检查len([]byte(pwd)) == 0 || len([]byte(pwd)) > 72 - 调用
bcrypt.GenerateFromPassword([]byte(pwd), bcrypt.DefaultCost),不是DefaultCost就够了,生产环境建议显式设为12或13(2026 年压测基准) - 拿到返回的
[]byte后,必须 转成string再赋值给结构体字段:user.Password = string(hashed) - 数据库字段类型必须是
VARCHAR(255)或TEXT;如果用 Beego ORM 的typetag,写成password string `orm:"size(255)"`
登录时用 bcrypt.CompareHashAndPassword 比对,顺序错就报错
Beego 的控制器里查出用户后,别手滑调用 bcrypt.GenerateFromPassword 再哈希一次——这是新手高频误操作。比对只用一个函数:bcrypt.CompareHashAndPassword,且参数顺序不可颠倒:
- 第一个参数是数据库读出的哈希值(
[]byte(user.Password)),必须是完整、未截断、无空格的 60 字节左右字符串 - 第二个参数是用户本次提交的明文密码(
[]byte(inputPwd)) - 如果传反了,会直接 panic 或返回
crypto/bcrypt: hashedPassword is not the hash of the given password - 查库前加一层保护:
if user.Password == ""或len(user.Password) != 60,立刻拒绝,避免无效比对
Beego 中容易被忽略的三处空值/格式污染点
Beego 的表单解析和 ORM 查询链路长,中间任何一环没清理干净,都会让 CompareHashAndPassword 静默失败:
-
ctx.Input.RequestBody解析 JSON 时,若前端传了"password": " 123 ",json.Unmarshal不会自动 trim,得手动strings.TrimSpace - Beego ORM 的
Read或QueryTable查出来字段若含 BOM、换行符或 \r\n(尤其从 Excel 导入测试数据时),len([]byte(user.Password))就不是 60 - MySQL 字段定义为
VARCHAR(60)且启用了严格模式,超长哈希会被截断;而 Beego 的orm.Read不报错,只读回一个残缺字符串
绕过 72 字节限制:sha256 + bcrypt 组合方案要改两处代码
当业务允许用户输入超长口令(如助记词、密语),不能简单截断,得用前置摘要。这不是 Beego 特有需求,但 Beego 项目里常被漏掉:
- 注册流程中,在调
bcrypt.GenerateFromPassword前,先做sha256.Sum256([]byte(pwd)).[:] → []byte,再把这个 32 字节切片喂给 bcrypt - 登录流程中,比对前也得对输入密码做同样
sha256摘要,再传给CompareHashAndPassword - 注意:这个组合方案下,
bcrypt的 cost 值建议提高到14,因为外层 sha256 极快,安全重心仍在 bcrypt 层
CompareHashAndPassword 就拒绝配合,还不会告诉你具体哪错了。


















