核心数据模型

数据是架构的底座

前面几章讨论的登录、Token、会话、SSO、OAuth、MFA,最后都要落到数据上。认证系统至少需要这些数据:

核心数据模型

六张表支撑完整的信任生命周期

user_account
用户账号、状态、密码哈希、认证方式
idemail / phonestatuspassword_hashauth_methods
session
登录设备、过期时间、撤销状态、风险等级
session_iduser_iddevice_idexpires_atrevoked_atrisk_level
refresh_token
长期凭证、轮换状态、绑定设备
token_hashsession_idrotated_atdevice_binding
identity_binding
OAuth、SSO 等外部身份绑定
user_idproviderexternal_subbound_at
mfa_factor
用户启用的 TOTP、WebAuthn、恢复码
user_idfactor_typesecret_encrecovery_codes
auth_audit_log
登录、失败、刷新、撤销、MFA、异常记录
eventuser_idip / deviceresultcreated_at
红色高亮字段(密码哈希、Refresh Token、MFA 密钥 / 备用码)属于高敏数据,必须加密或哈希存储,绝不能明文落库。

高敏数据的安全处理

红色的字段(密码哈希、Refresh Token、MFA 密钥 / 备用码)属于高敏数据:

  • 密码:慢哈希 + 盐,绝不存明文、不存可逆加密。
  • Refresh Token:存哈希(token_hash),不存原文,防止库泄露直接可用。
  • MFA 密钥 / 备用码:加密存储,备用码额外做哈希、一次性。

数据之间的关系

六张表的关系大致是:

user_account(用户主表)
  ├── session(登录设备 / 会话,挂在用户下)
  │     └── refresh_token(长期凭证,挂在会话下)
  ├── identity_binding(外部身份 -> 本地用户 的映射)
  └── mfa_factor(用户启用的 MFA 因子)

auth_audit_log(旁路,记录所有认证事件)

会话、Refresh Token 都以 user_id 为外键;撤销会话时,挂在其下的 Refresh Token 一起失效。

一张表的取舍

会话表要不要存? 前面说过:即使用了 JWT 也建议保留。它支撑设备管理、强制下线、风险审计。代价是每次请求多一次查询——用 Redis 存会话,查询快、带 TTL,正好合适。

审计表会长得很大。 登录、刷新、撤销、MFA 都要记,数据量增长快。方案是:分表 / 冷热分层 / 只保留最近 N 天在线,历史归档(这和 API 平台课程的日志治理思路一致)。

小结

  • 六张核心表覆盖认证的完整生命周期。
  • 高敏字段必须加密或哈希存储。
  • 会话、Refresh Token 通过外键联动,撤销要能成链。
  • 审计日志要能长大、能归档。

数据层打好了,下一节看一次最终登录在真实系统里是怎么走完全链路。

发现内容有问题?

告诉我们哪里需要改进。