第1章:身份认证与访问控制
大家好,我是你们这堂课的老朋友。今天咱们聊聊安全架构里最基础、也最要命的一块——身份认证与访问控制。
说白了,就是两件事:「你是谁?」 和 「你能干什么?」
我做了十几年安全架构,见过太多系统在这上面栽跟头。有的公司上了最牛的防火墙,结果内部一个弱口令就全完蛋。有的用了最复杂的算法,结果权限模型一团浆糊,普通员工能看到CEO的工资单。
嗯,咱们今天就把这块彻底捋清楚。
核心观点:认证是门锁,授权是房间里的权限。门锁再结实,房间里东西乱放也不行。反过来,房间管理得再好,门锁一捅就开,也是白搭。
一、认证机制:你到底是谁?
认证,就是验证用户身份的过程。你想想看,如果连门都看不住,后面再好的权限设计也是白搭。
1. 密码认证
最古老、也最常用的方式。但我得说句实话——密码本身就是个妥协方案。
我在项目中遇到过一家公司,密码策略是「8位以上,必须包含大小写、数字、特殊字符」。听起来很安全对吧?结果员工全把密码贴在显示器上。为什么?因为记不住啊。
我的建议:别把密码策略搞得太变态。与其要求「P@ssw0rd!2024」这种反人类的密码,不如鼓励用户用「正确-马-电池-订书机」这种长短语。长度才是密码安全的第一要素。
存储密码时,记住一个铁律:永远不要明文存储。要用加盐的哈希算法,比如 bcrypt、scrypt 或 Argon2。
// 错误示范(我见过太多人这么干了)
String password = request.getParameter("password");
saveToDatabase(password); // 明文存储!找死!
// 正确做法
String salt = generateSalt();
String hashedPassword = bcrypt.hash(password, salt);
saveToDatabase(hashedPassword, salt);
警告:MD5 和 SHA-1 已经不够用了。别再用它们做密码哈希。我曾经审计过一个项目,他们用 MD5 哈希密码,连盐都没加。结果数据库泄露后,彩虹表一跑,80% 的密码直接还原。
2. 多因素认证(MFA)
光有密码不够。为什么?因为密码太容易被偷了。钓鱼、撞库、键盘记录器……手段多得很。
多因素认证,说白了就是「你知道的 + 你拥有的 + 你本身的」至少组合两种。
- 你知道的:密码、PIN码
- 你拥有的:手机(短信验证码)、硬件密钥(YubiKey)、TOTP 应用(Google Authenticator)
- 你本身的:指纹、人脸、虹膜
我个人习惯是:所有面向外网的系统,强制开启 MFA。内网系统至少也要支持可选。别嫌麻烦,真出了事更麻烦。
避坑指南:我曾经帮一家金融公司做安全评估。他们上了短信验证码做 MFA,看起来没问题。但后来发现,攻击者通过 SIM 卡交换攻击,直接把验证码劫持了。从那以后,我强烈推荐用 TOTP 或硬件密钥,而不是短信。
3. 生物识别
指纹、人脸、声纹……这些听起来很酷,但也不是万能的。
生物识别的最大问题是:它不可撤销。密码泄露了可以改,指纹泄露了你能换手指吗?
所以我的建议是:生物识别适合做辅助认证,或者低安全场景的便捷登录。真正的高安全场景,还是得靠密码 + 硬件密钥的组合。
二、授权模型:你能干什么?
认证完了,接下来就是授权。说白了,就是「你进来了,但你能碰哪些东西?」
1. RBAC(基于角色的访问控制)
这是最经典的模型。把权限打包成「角色」,然后把角色分配给用户。
比如:管理员、编辑、普通用户。每个角色有一组权限。用户是什么角色,就有什么权限。
我的经验:RBAC 适合权限结构相对稳定的系统。我在做电商平台时,就用 RBAC 管理后台权限。运营、客服、财务各司其职,清晰明了。
但 RBAC 有个问题——粒度不够细。比如「编辑」角色能编辑所有文章,但你可能只想让某个编辑只能编辑科技类的文章。这时候就需要 ABAC 了。
2. ABAC(基于属性的访问控制)
ABAC 不看角色,看属性。用户的属性、资源的属性、环境的属性,组合起来做决策。
举个例子:
- 用户属性:部门=技术部,职级=高级
- 资源属性:文档分类=技术文档,密级=内部
- 环境属性:时间=工作时间,IP=公司内网
策略可以写成:「允许技术部高级员工在工作时间从内网访问内部技术文档」。
你看,比 RBAC 灵活多了吧?但代价是——策略管理复杂。属性一多,策略就乱。我见过一个项目,ABAC 策略写了上千条,最后没人敢改。
3. PBAC(基于策略的访问控制)
PBAC 是 ABAC 的进化版。它把权限决策抽象成「策略引擎」,用统一的语言(比如 XACML 或 ALFA)来描述策略。
说白了,PBAC 就是给 ABAC 加了一层「策略管理框架」。让策略的编写、测试、审计都变得规范。
| 模型 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| RBAC | 简单、直观、易管理 | 粒度粗,灵活性差 | 权限结构稳定的系统 |
| ABAC | 粒度细,灵活性强 | 策略复杂,管理成本高 | 需要细粒度控制的系统 |
| PBAC | 标准化、可审计、可扩展 | 实现复杂,学习曲线陡 | 大型企业级系统 |
三、会话管理与令牌机制
认证通过了,授权也配好了。但用户每次请求都要重新认证吗?当然不。这时候就需要会话管理和令牌机制了。
1. 会话管理
传统的会话管理,就是服务端存一个 session,客户端存一个 session ID(通常放在 cookie 里)。
但这种方式有个问题——服务端有状态。如果做负载均衡,session 得共享,不然用户请求打到不同服务器就掉线了。
注意:我曾经遇到过一个项目,session 存在本地内存里,没做共享。结果上线后用户频繁掉线,排查了半天才发现是负载均衡的问题。后来改用 Redis 做 session 共享才解决。
2. JWT(JSON Web Token)
JWT 解决了「有状态」的问题。它把用户信息加密后放在 token 里,服务端不需要存 session,直接验证 token 就行。
一个 JWT 长这样:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
它由三部分组成:Header、Payload、Signature。用 Base64 编码,最后用密钥签名。
但 JWT 也有坑:
- 无法撤销:token 发出去了,除非等它过期,否则没法让它失效。所以过期时间要设短一点。
- Payload 是明文:别把密码、信用卡号放进去。Base64 不是加密,是编码。
我的习惯:JWT 的过期时间设 15-30 分钟。配合 refresh token 使用。这样即使 token 泄露,损失也有限。
3. OAuth 2.0
OAuth 2.0 不是认证协议,是授权协议。它解决的是「第三方应用如何安全地访问用户资源」的问题。
比如你用微信登录某个网站,网站不会拿到你的微信密码,而是通过 OAuth 2.0 拿到一个临时的 access token,用这个 token 去获取你的基本信息。
OAuth 2.0 有四种授权模式:
- 授权码模式:最安全,适合有后端的应用
- 隐式模式:适合纯前端应用(现在不推荐了)
- 密码模式:直接拿用户名密码换 token(尽量别用)
- 客户端凭证模式:适合服务间调用
我个人建议:能用授权码模式就别用别的。隐式模式已经被 OAuth 2.1 废弃了,密码模式说白了就是把密码交给第三方,风险太大。
总结一下:认证是基础,授权是核心,会话和令牌是桥梁。这三块做好了,系统的安全就有了八成把握。剩下的两成,靠的是持续的安全审计和应急响应。
嗯,今天就聊到这儿。内容不少,但都是干货。你回去可以看看自己负责的系统,这三块做得怎么样。有问题随时找我聊。