2、身份认证与访问控制:IAM基础、MFA多因素认证、SSO单点登录、RBAC权限模型
大家好,我是你们的老朋友。今天咱们聊聊SaaS安全里最基础、也最要命的一块——身份认证与访问控制。
说白了,就是解决三个问题:你是谁?你怎么证明?你能干什么?
我见过太多初创SaaS公司,一开始图省事,用户名密码一把梭。结果呢?要么被撞库,要么内部员工越权删库跑路。嗯,今天咱们就把这块彻底捋清楚。
2.1 IAM基础:别把门钥匙挂在门框上
IAM,Identity and Access Management,身份与访问管理。听起来高大上,其实就是一套管“人”和“权限”的体系。
我个人习惯把IAM拆成三块看:
- 身份库:用户到底是谁?存在哪?LDAP?AD?还是自建用户表?
- 认证:你怎么证明你是你?密码?指纹?还是硬件Key?
- 授权:证明完了,你能干啥?看数据?改配置?还是只能读报表?
我在项目中遇到过一家客户,他们的管理员账号居然用“admin/123456”。我问为什么不改?答曰:“内网用,没事。”结果三个月后被人从外网扫到了弱口令,数据库被拖了个干净。你说冤不冤?
我曾经接手过一个项目,IAM系统里居然有超过40%的“僵尸账号”——员工离职两年了,账号还活着。这些账号就是定时炸弹。建议:定期做账号审计,至少每季度一次。
2.2 MFA多因素认证:一道锁不够,那就上两道
密码这玩意儿,说实话,已经不太靠谱了。你想想看,多少人所有网站用同一个密码?
MFA,Multi-Factor Authentication,多因素认证。它的核心逻辑是:你要证明你是你,得拿出至少两种不同类型的证据。
常见的因素分三类:
| 因素类型 | 举例 | 安全性 |
|---|---|---|
| 你知道的(知识) | 密码、PIN码 | 低(容易被猜/钓鱼) |
| 你拥有的(持有) | 手机、硬件Key、TOTP令牌 | 中(可能丢失/被盗) |
| 你本身的(固有) | 指纹、人脸、虹膜 | 高(难以复制) |
我建议SaaS系统至少上两层:密码 + TOTP(基于时间的一次性密码)。为什么?因为硬件Key成本高,生物识别在Web端兼容性差。TOTP是性价比最高的选择。
别把MFA做成“可选”功能。我见过太多用户嫌麻烦,勾选“下次不再提醒”。强制MFA,尤其是对管理员账号,这是底线。
代码实现一个简单的TOTP验证逻辑,其实不复杂:
// 伪代码:验证TOTP
function verifyTOTP(secret, userCode) {
// 1. 获取当前时间戳(30秒窗口)
let timeSlice = Math.floor(Date.now() / 1000 / 30);
// 2. 用HMAC-SHA1生成一次性密码
let expectedCode = generateHOTP(secret, timeSlice);
// 3. 比对
return userCode === expectedCode;
}
嗯,这里要注意:时间同步是个坑。用户手机时间不准,验证就会失败。我一般会允许前后各一个时间窗口的偏移,也就是允许用户输入前30秒或后30秒的验证码。
2.3 SSO单点登录:一次登录,到处通行
你想想看,一个企业用了几十个SaaS应用,每个都要注册、记密码、登录。员工不疯才怪。
SSO,Single Sign-On,单点登录。它的核心是:你在一个地方登录了,其他系统自动信任你。
主流协议就两个:
- SAML 2.0:老牌协议,企业级应用标配。基于XML,较重,但成熟稳定。
- OIDC (OpenID Connect):基于OAuth 2.0,轻量级,用JWT传身份信息。现代SaaS更爱用这个。
我个人更倾向OIDC。为什么?因为JWT是JSON格式,前后端解析都方便。而且OIDC天然支持API鉴权,SAML在这方面就比较笨重。
实现SSO时,一定要处理好Session超时和登出。我曾经遇到一个坑:用户在A应用登出了,但B应用的Session还在,结果别人用同一台电脑直接进了B系统。这叫“单点登出(SLO)没做好”。建议用反向通道通知,确保所有关联系统同步销毁Session。
2.4 RBAC权限模型:别让所有人都拿着万能钥匙
权限控制,最怕什么?最怕“一放就乱,一管就死”。
RBAC,Role-Based Access Control,基于角色的访问控制。它的思路很简单:不直接给人权限,而是给人角色,角色再绑定权限。
举个例子:
- 张三入职了,他是“客服专员”。
- “客服专员”这个角色,只能查看工单、回复客户。
- 张三不能删除工单,也不能查看财务报表。
这样,权限管理就变成了角色管理。人流动再快,角色不变,权限就不会乱。
我建议的RBAC模型分三层:
| 层级 | 说明 | 示例 |
|---|---|---|
| 用户 | 具体的人或服务账号 | 张三、李四、支付服务 |
| 角色 | 权限的集合 | 管理员、编辑者、查看者 |
| 权限 | 对资源的操作 | 创建订单、删除用户、导出报表 |
我曾经见过一个系统,RBAC里搞了200多个角色。为什么?因为每个用户都想要“一点点定制权限”。结果角色比人还多,管理成本爆炸。
我的建议:角色数量控制在10个以内。如果不够,说明你的权限粒度设计有问题,而不是角色不够用。
代码层面,RBAC的鉴权逻辑其实就是一个查表过程:
// 伪代码:检查用户是否有权限
function checkPermission(userId, resource, action) {
// 1. 查用户角色
let roles = getRolesByUserId(userId);
// 2. 查角色权限
let permissions = getPermissionsByRoles(roles);
// 3. 判断是否包含目标权限
return permissions.some(p =>
p.resource === resource && p.action === action
);
}
嗯,这里要注意性能。如果每次请求都查数据库,高并发下会崩。我一般会在Redis里缓存用户的权限列表,缓存时间设5分钟。权限变更时,主动清除相关缓存。
2.5 总结:四者如何协同?
最后,咱们把这四块串起来,看看一个完整的认证授权流程长什么样:
- 用户访问SaaS → 跳转到SSO登录页(OIDC协议)。
- 输入密码 + MFA验证码 → 身份认证通过。
- SSO生成JWT Token → 返回给前端,前端存到LocalStorage或Cookie里。
- 前端请求API → 带上JWT Token。
- 后端解析JWT → 拿到用户ID,查RBAC权限表。
- 权限校验通过 → 返回数据。否则返回403。
说白了,IAM是地基,MFA是门锁,SSO是走廊,RBAC是房间钥匙。缺一个,整个安全体系就漏风。
我做了这么多年安全,最大的感触是:安全不是加功能,而是设计习惯。把认证和权限的流程想清楚,比堆砌一百个安全产品都管用。
好,今天就聊到这儿。下一章咱们讲讲数据加密与密钥管理——嗯,那又是另一个有意思的话题了。