设计原则
设计认证系统时踩过的坑,让我总结出几条可以复用到其他系统的原则。
1. 信任分层
原则
不要把所有信任问题都堆在登录这一步。
实践
登录只是建立信任的第一步。认证系统要分层处理:用凭证建立信任,用会话延续信任,用风控和 MFA 提升信任,用撤销收回信任,用审计追踪信任。每一层都有自己的职责,不要指望一个接口解决所有安全诉求。
2. 最小暴露
原则
不给用户和系统暴露不必要的敏感信息。
实践
登录失败时不要区分”账号不存在”和”密码错误”,统一提示”账号或密码错误”。OAuth scope 最小化,只申请登录所需的信息。错误提示、日志、报错页面,都不要泄露内部实现细节。
3. 默认安全
原则
安全的默认值,而不是可选的开关。
实践
密码默认用 bcrypt/scrypt/Argon2 慢哈希加盐;Token 默认短有效期;Cookie 默认 HttpOnly + Secure + SameSite;新设备登录默认触发风控。所有安全措施默认开启,特殊情况再放宽,而不是反过来。
4. 可撤销优先
原则
任何凭证都能在必要时被收回。
实践
Access Token 可能被盗,Refresh Token 可能泄露,设备可能丢失。设计时要先回答”怎么撤销”,再谈”怎么签发”。JWT 撤销难,就用短有效期 + 会话记录 + 黑名单;不透明 Token 好撤销,就承担查询成本。
5. 风险驱动的体验
原则
验证强度跟随风险,而不是一刀切。
实践
MFA 不需要每次登录都触发。新设备、异地、高风险操作才需要强验证;常用设备、低风险场景应该顺滑。这叫自适应认证:把额外摩擦放在风险最高的地方,而不是让所有用户都为低概率风险买单。
6. 会话是状态,不只是凭证
原则
即使用了 JWT,也保留服务端会话记录。
实践
会话记录支撑设备管理、强制下线、风险审计和刷新令牌撤销。没有会话记录,遇到账号被盗就难以识别异常设备、无法精准下线。JWT 适合传输身份,会话记录负责管理状态。
7. 敏感操作二次确认
原则
修改身份信息前,先确认是用户本人。
实践
改密码、改邮箱、改手机号、解绑第三方账号,都要重新验证当前身份或触发 MFA。攻击者拿到一个泄露的会话,不应该能顺手改掉账号的绑定信息,把账号彻底据为己有。
8. 审计先行
原则
登录、刷新、撤销、MFA 都要留下可追踪的日志。
实践
账号被盗时,审计日志是唯一能还原”发生了什么、从哪来的、动了什么”的手段。审计日志本身要防篡改,记录 IP、设备、地域、操作类型和结果,并进入风控或告警系统。
认证系统设计 checklist
密码与凭证:
✓ 密码使用慢哈希 + 盐
✓ 高敏数据(Refresh Token / 备用码)加密存储
登录安全:
✓ 账号 / IP / 设备多维限流
✓ 错误提示不泄露账号是否存在
✓ 高风险登录触发风控或 MFA
令牌与会话:
✓ Access Token 短期有效
✓ Refresh Token 可撤销、可轮换
✓ 会话支持多设备管理和强制下线
✓ 改密 / 冻结后撤销旧会话
第三方与联邦:
✓ OAuth 校验 state 和 redirect_uri 白名单
✓ SSO 定义全局会话 / 本地会话 / 登出策略
✓ scope 最小授权
风险与审计:
✓ 高风险操作触发 MFA 或重新认证
✓ 登录 / 刷新 / 撤销 / MFA 有审计日志
✓ 异常登录进入风控或告警
记住:
- 认证系统的本质是信任管理,不是登录接口
- 安全默认开启,体验基于风险自适应
- 可撤销永远优先于便捷
- 审计日志是账号安全事件的最后防线
