应直接使用 bcrypt 而非手写 salt+sha-256,因其内置安全盐值、可调迭代成本、标准化编码及自动解析验证;fiber 中推荐用 golang.org/x/crypto/bcrypt 封装哈希逻辑,避免手动拼接导致的兼容性与安全性问题。

直接用 bcrypt,别自己拼接 salt + hash;Fiber 默认不带密码处理能力,得靠成熟库封装逻辑,否则极易出错。
为什么不能手写 salt + SHA-256 拼接
常见错误是生成随机 salt,再用 sha256(password + salt) 存进数据库。这看似加盐,实则漏洞百出:
- SHA-256 迭代次数固定、无内存消耗,GPU/ASIC 可暴力穷举每秒数亿次
- 拼接顺序没规范(
password+salt还是salt+password?不同实现不兼容) - 盐长度随意(8 字节太短,16 字节才勉强够用),且未做编码标准化(Base64 还是 hex?)
- 验证时需手动提取 salt、重新拼接、再哈希——容易漏掉 trim、大小写、编码转换等细节
Fiber 中推荐用 golang.org/x/crypto/bcrypt
Go 生态里最稳妥的选择就是官方维护的 bcrypt 包,它把 salt 生成、编码、哈希、验证全包进一个函数里,无需你操心格式或顺序:
-
bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)返回完整哈希字符串,形如$2a$10$...,其中已内嵌 salt 和 cost 参数 -
bcrypt.CompareHashAndPassword(hashed, []byte(input))自动解析哈希串里的 salt 并重算比对,不暴露中间值 - 默认
DefaultCost = 10,可按服务器性能调高(12–14 更安全,但注册耗时增加) - 不依赖外部配置或全局状态,天然适合 Fiber 的无状态中间件风格
在 Fiber 路由中集成注册与登录逻辑
不要在 handler 里裸写哈希逻辑,应封装成可复用函数,并注意错误处理边界:
- 注册时:接收明文
password→ 调用bcrypt.GenerateFromPassword→ 存入数据库字段(建议用TEXT类型,长度 ≥ 60) - 登录时:查出用户记录 → 用
bcrypt.CompareHashAndPassword验证,**绝不**先取 hash 再手动比对字符串 - 若验证失败,统一返回
401 Unauthorized,不区分“用户不存在”和“密码错误”,防枚举攻击 - 敏感操作(如登录、修改密码)建议加简单限流,避免暴力试探,可用
fiber/adaptor接入github.com/ulule/limiter
容易被忽略的存储与迁移细节
生产环境最容易翻车的地方不在代码,而在 schema 和历史数据:
- 数据库字段必须足够长:
CHAR(60)不够,TEXT更稳妥,因为bcrypt输出长度随 cost 上升(cost=14 时可达 63 字符) - 已有明文或弱哈希密码的旧数据,不能直接覆盖;要设计渐进式迁移:首次登录时用旧逻辑校验,成功后立即用
bcrypt重哈希并更新字段 - 别把 salt 单独建一列——
bcrypt哈希串里已含 salt,拆出来反而破坏标准、增加出错面 - 测试时务必覆盖空密码、超长密码(>72 字节会被
bcrypt截断)、含 null 字节的输入等边界情况
真正难的不是调通 bcrypt,而是确保每次密码变更都走同一套不可绕过的路径——包括 CLI 工具批量导入、管理后台重置、甚至数据库直连修复场景。这些地方一旦漏掉哈希环节,整套防护就归零。











