关键决策

这一页整理认证系统设计过程中遇到的关键决策点。每个决策都说明了问题、对比过的方案和最终选择理由。

决策 1:不透明 Token 还是 JWT

问题

用户登录后,后续请求用什么凭证证明身份?

方案对比

方案撤销跨服务验证存储典型场景
不透明 Token容易需查服务端数据库/缓存单服务、需强撤销
JWT困难离线验证无状态分布式、跨服务传递

决策

高安全场景用短期 JWT + 服务端会话的组合:JWT 承担跨服务传递,会话记录承担撤销和审计。如果撤销需求特别强(如金融、账号风控),优先不透明 Token。

决策 2:Cookie 还是 Authorization Header

问题

浏览器端登录态放在哪里?

方案对比

  • Cookie(HttpOnly + Secure + SameSite):降低 XSS 读取风险,但要处理 CSRF。
  • Authorization Header(LocalStorage/内存):实现简单,适合 API 和移动端,但更容易被 XSS 窃取。

决策

浏览器端优先 HttpOnly Cookie,让脚本读不到 Token,把 XSS 风险挡在门外;CSRF 用 SameSite + 校验来源处理。移动端和纯 API 场景用 Authorization Header,重点防 XSS 和本地存储泄露。

决策 3:Access Token 与 Refresh Token 拆分

问题

单一 Token 要么有效期短(体验差),要么有效期长(风险大),如何平衡?

决策

拆成两个 Token:Access Token 短期有效(分钟到小时级),用于访问 API;Refresh Token 长期有效,用于换新。同时给 Refresh Token 做轮换(每次刷新换新值)、绑定设备和可撤销。这样 Access Token 泄露的风险窗口短,Refresh Token 泄露可以通过设备绑定和重放检测发现。

决策 4:会话过期策略

问题

会话多久过期?固定过期还是滑动过期?

方案对比

  • 固定过期:登录后 7 天必须重新登录,安全但体验差。
  • 滑动过期:持续活跃自动延长,体验好但风险窗口大。

决策

组合使用:短期 Access Token + 较长 Refresh Token + 最长会话生命周期。用户持续活跃时用 Refresh Token 续期,但设定一个绝对上限(如 30 天),超过就必须重新登录。既照顾体验,又控制风险。

决策 5:MFA 是否每次触发

问题

MFA 增强安全,但每次都触发会严重伤害用户体验。

决策

采用自适应 MFA:新设备、异地、高风险操作才触发;常用设备、低风险场景直接放行。通过 MFA 后给会话记录 assurance_level = high,在一定时间内敏感操作不再重复验证,超过有效期或风险变化后再要求重新验证。

决策 6:SSO 是否统一登出

问题

用户在认证中心退出后,业务系统本地会话是否也要失效?

方案对比

  • 前端重定向通知:实现简单,但依赖浏览器跳转,不可靠。
  • 后端通道通知:可靠,但要维护各系统回调。
  • 缩短本地会话:降低残留风险,但体验略差。

决策

内部管理系统要求统一登出(后端通道为主),普通内容站点可以放宽。统一登出越彻底,实现越复杂,安全要求决定投入程度。

决策 7:第三方登录后账号怎么建

问题

用户用 GitHub/微信登录,本地系统如何绑定和创建账号?

决策

本地系统保留自己的用户 ID,外部平台的 openid 只作为 identity_binding 存储,不作为内部主键。第一次第三方登录时按策略自动建号或引导绑定;用户可解绑;第三方撤销授权后,本地会话按风险降级处理。这样用户换身份来源也不会丢失本地数据。

决策 8:密码哈希算法

问题

密码如何存储才安全?

决策

带盐的慢哈希算法(bcrypt / scrypt / Argon2),数据库只保存 password_hash、算法版本和参数。绝不使用 MD5/SHA 等快速哈希(容易被 GPU 暴力破解),也绝不存储明文或可逆加密。算法升级时保留版本号,支持渐进式迁移。