4. 身份认证与授权:密码存储策略(哈希加盐)、多因素认证(MFA)、基于角色的访问控制(RBAC)

身份认证和授权,是软件安全的第一道门。说白了,就是解决两个问题:「你是谁?」和「你能干什么?」。我见过太多项目,功能做得花里胡哨,结果在登录环节就被人捅穿了。这一章,咱们就把这三块硬骨头啃下来。

4.1 密码存储策略:别再存明文了

先聊个老生常谈但总有人踩坑的话题——密码怎么存。我记得刚入行那会儿,接手过一个遗留系统,打开数据库一看,用户密码字段存的居然是明文。我当时后背一凉,连夜给老板写了份整改报告。

⚠️ 铁律:永远不要存储用户的明文密码。一旦数据库泄露,你就是在帮黑客开「全自动撞库大会」。

4.1.1 哈希 + 盐:标准做法

正确的做法是:哈希 + 盐。哈希是单向函数,把密码变成一串固定长度的乱码。但光哈希不够——如果两个用户密码相同,哈希值也一样,黑客可以用彩虹表反向查出来。所以得加盐。

盐(Salt)是一段随机字符串,每个用户都不一样。存储时,我们把盐和密码拼在一起再哈希。这样,就算两个用户密码相同,哈希值也完全不同。

✅ 推荐算法:bcrypt、scrypt、Argon2。这些算法自带盐,而且可以调节计算成本,让暴力破解变得极其缓慢。

我个人习惯用 bcrypt,因为它实现简单,社区支持好。下面是一个伪代码示例:

// 注册时
salt = generateRandomSalt(16 bytes)
hash = bcrypt(password + salt)
存储: username | salt | hash

// 登录时
从数据库取出 salt 和 hash
if bcrypt(inputPassword + salt) == hash:
    登录成功
else:
    登录失败
💡 避坑指南:我曾经见过有人用 MD5 加固定盐(比如 "abc123")来存密码。这跟没加盐差不多——黑客拿到一个盐就能解所有用户。记住:盐必须随机,每个用户独立。

4.1.2 常见哈希算法对比

算法 安全性 速度 推荐场景
MD5 ❌ 极低(已破解) 极快 不要用
SHA-256 ⚠️ 中等(无盐时易受彩虹表攻击) 快 仅用于完整性校验
bcrypt ✅ 高(自带盐,可调成本) 慢(可控) 密码存储(推荐)
Argon2 ✅ 最高(抗 GPU/ASIC) 慢(可控) 密码存储(新项目首选)

4.2 多因素认证(MFA):加把锁

光靠密码,风险太大了。密码可能被钓鱼、被撞库、被社工。所以,我们需要多因素认证(MFA)。它的核心思想是:至少用两种不同类型的证据来证明你是谁。

三种常见的认证因素:

  • 知识因素:你知道的东西(密码、PIN码)
  • 持有因素:你拥有的东西(手机、硬件令牌)
  • 固有因素:你是什么(指纹、人脸)

MFA 就是把这些因素组合起来。比如:密码(知识)+ 手机验证码(持有),或者密码 + 指纹(固有)。

✅ 推荐方案:TOTP(基于时间的一次性密码)。用户用 Google Authenticator 或 Authy 扫码绑定,每 30 秒生成一个 6 位数字。服务器端验证这个数字。实现简单,安全性高。

我曾经在一个金融项目中,强制要求所有管理员开启 MFA。结果上线第二天,就有人抱怨「太麻烦了」。但三个月后,我们拦截了一次针对高管账号的钓鱼攻击——对方拿到了密码,但过不了 TOTP 验证。从那以后,再没人抱怨了。

⚠️ 注意:短信验证码(SMS OTP)虽然也是 MFA,但存在 SIM 卡劫持风险。如果条件允许,优先用 TOTP 或硬件密钥(如 YubiKey)。

4.3 基于角色的访问控制(RBAC)

认证通过后,就该授权了。RBAC 是目前最主流的授权模型。它的核心是:把权限分配给角色,再把角色分配给用户。这样,你不需要给每个用户单独配权限,管理起来轻松得多。

4.3.1 核心概念

  • 用户(User):系统的操作者
  • 角色(Role):一组权限的集合(如「管理员」、「编辑者」、「访客」)
  • 权限(Permission):对某个资源的操作(如「创建文章」、「删除用户」)
  • 会话(Session):用户激活的角色集合

你想想看,一个电商系统,可能有几十种操作权限。如果每个用户单独配,光配权限就能累死人。用 RBAC,你只需要定义几个角色:

角色 权限示例
超级管理员 所有权限
商品管理员 创建/编辑/删除商品、查看订单
客服 查看订单、处理退款
普通用户 浏览商品、下单、查看自己的订单

然后,把用户丢进对应的角色里就行了。简单、清晰、可审计。

4.3.2 RBAC 的常见坑

💡 避坑指南:我曾经在一个项目中,把权限粒度设计得太细——每个按钮都是一个独立权限。结果角色数量爆炸,管理员配权限时一脸懵。后来我们重新梳理,把权限合并成「模块级」和「操作级」两层,才解决问题。记住:权限粒度要适中,太细了反而难用。

4.4 知识结构图:身份认证与授权全景

下面这张图,把本章的核心知识点串起来了。你可以把它当作一个快速参考。

身份认证与授权知识结构图 身份认证与授权知识结构 密码存储策略 多因素认证 (MFA) 基于角色的访问控制 哈希 + 盐 bcrypt/Argon2 TOTP 硬件密钥 用户→角色 角色→权限 核心原则 密码不存明文 · 认证多因素 · 授权按角色 · 权限最小化 身份认证 授权 访问资源 认证通过后,系统根据用户角色决定其可访问的资源

4.5 实践建议:从设计到落地

最后,分享几条我在项目中总结出来的经验:

  1. 密码策略别太复杂:要求大小写+数字+特殊字符+16位,用户记不住,最后全贴在显示器上。建议用长密码(passphrase)代替复杂密码,比如「我喜欢吃火锅2024」比「P@ssw0rd!」安全得多。
  2. MFA 要渐进式推广:先让管理员强制开启,再逐步推广到普通用户。别一上来就全员强制,否则客服电话会被打爆。
  3. RBAC 要定期审计:权限不是配完就完事了。我建议每季度检查一次角色和权限,看看有没有「僵尸角色」或「权限膨胀」。
  4. 日志记录不能少:谁、在什么时间、通过什么方式、访问了什么资源,这些都要记下来。出了问题,日志就是你的救命稻草。
✅ 一句话总结:密码加盐哈希保底,MFA 上强度,RBAC 管权限。这三板斧砍下去,大部分身份认证相关的漏洞都能防住。