Skip to content

认证边界与方案选择 ​

认证建立的是请求与主体之间的可信关联。这个主体可能是个人账号,也可能是服务账号;业务系统仍需要判断账号状态、组织成员资格和资源权限。

OWASP 的认证说明区分了身份认证与身份核实:证明能控制某个账号,并不自动证明其现实身份。手机验证码通常证明此时能接收该号码的消息,实名认证需要额外的证据与业务流程。

六个容易混在一起的对象 ​

对象职责不应承担的职责
账号 user_id应用内稳定的主体标识直接充当秘密凭据
登录标识帮助定位账号,如用户名、邮箱单凭标识判定本人操作
认证器或凭据提供身份证明,如密码、私钥决定全部业务权限
Session维护一次登录后的上下文与有效状态替代资源级授权
Token携带或引用某项凭证、授权结果因为名字叫 Token 就被信任
权限策略判断主体对资源的动作通过隐藏按钮替代后端检查

Cookie 是浏览器保存并发送数据的机制;Session 是登录状态模型;JWT 是声明的编码与保护格式。三者不在同一层,可以组合:Cookie 里既能放随机 Session ID,也能放签名令牌。安全特征取决于完整方案。

一次受保护请求的判断链路如下。认证得到主体后,账号、成员和资源权限仍需要按业务要求检查。

状态检查覆盖账号是否可用,以及当前操作所需的组织成员资格;资源授权判断主体能否执行本次动作。令牌的密码学验证通过后,后续检查仍遵守业务要求的状态新鲜度。

三种常见请求链路 ​

服务端 Session ​

浏览器持有随机会话凭据,服务端查询会话记录,得到账号和认证上下文。账号封禁或退出时修改服务端状态,后续请求读取到新状态就会拒绝访问。

这种方案容易实现设备列表和精确撤销,代价是每次请求的存储或缓存查询。把会话库换成 Redis 只改变存储性能,不会自动解决故障恢复和撤销一致性。具体见 Session 设计。

本地验证 Access Token ​

API 验证签名和声明后读取主体,不必每次询问签发方。签发方短时不可达时,已缓存密钥的服务仍可能接受未过期令牌。

下图中 API 已持有可信的验证密钥。签名与声明在本地校验,账号状态与权限是否在线查询,由各操作的时效要求决定。

代价是账号状态和权限容易滞后。若要求封禁立即生效,就要增加状态查询、撤销列表或事件传播;此时不能再把整个系统称为“完全无状态”。RFC 7662定义了查询令牌活动状态的 introspection 机制,能集中控制有效性,也增加在线依赖。

浏览器通过 BFF 访问 API ​

BFF(Backend for Frontend)是专门服务某类前端的后端。浏览器与 BFF 使用 Cookie 会话,BFF 保存上游令牌并调用 API,减少令牌暴露给页面脚本的机会。

以一次状态变更请求为例,浏览器持有本地会话凭据,上游 Access Token 保存在 BFF 服务端。

BFF 增加一次代理、会话存储和扩容成本,也仍需 CSRF 防护、输出编码和请求目标限制。它适合已有后端、且希望统一管理浏览器认证的应用;对于原生移动端,需要另外设计授权码与安全存储流程。

按客户端选择方案 ​

下表是方案评估起点,不是协议对客户端的唯一限制。

场景优先评估主要代价
自有同源网站服务端 Session在线状态存储与容量
浏览器调用多个后端BFF + 本地会话代理成本、CSRF 与接口边界
原生移动应用系统浏览器授权码 + PKCE回调配置、令牌存储和刷新
直接访问 API 的 SPA授权码 + PKCE,审查浏览器令牌暴露XSS、刷新与跨域复杂度
企业统一登录OIDC 或对接企业现有 SAML联合身份映射、退出和撤权
第三方代用户调用 APIOAuth 委托授权客户端、scope、同意与撤销管理

原生应用与 SPA 无法可靠保守一个随客户端分发的固定 client_secret,应按公共客户端设计。OAuth 流程与 PKCE 要求见 RFC 9700 §2.1;不能把客户端内置字符串当作服务端身份凭据。

认证上下文比用户 ID 更丰富 ​

敏感操作往往需要知道“最近如何证明过身份”。建议在服务端维护:

字段用途
user_id、session_id主体和本次登录实例
authenticated_at首次完成认证的时间
reauthenticated_at最近重新认证的时间
auth_methods实际通过的密码、OTP、WebAuthn 等方式
assurance_policy应用内部通过的策略标识
security_version账号安全变更版本

“已使用 MFA”不等于永远可以修改收款账户。业务可要求在短时间内重新认证,并将提升结果绑定到目标操作。外部 OIDC 的 acr、amr 值还需要与提供方约定含义,不能直接把任意字符串解释成满足本地高强度策略。

用户身份与服务身份 ​

定时任务、服务间调用和自动化客户端应使用独立机器身份,避免保存员工密码来模拟登录。服务可以代表自己,也可以在明确授权的链路中代表用户;两者要分别记录,以免审计中只有一个无法解释的 user_id。

网关传入的用户头只有在下游无法被外部直接访问、网关清除了外来同名头、内部连接受保护时才可信。是否经过网关不能由客户端自己提供一个布尔字段证明。

自建与接入身份提供方 ​

成熟身份提供方可以承担协议、密钥、认证器与联合登录。应用仍需维护账号与外部身份映射、业务状态、租户成员和资源权限。

选择时应实际验证:导出和迁移能力、账号恢复、单点退出、租户隔离、审计事件、灾备与不可用时的行为。托管服务减少的是实现与运维工作,同时引入外部依赖;自建则需要持续承担协议升级和安全修复。

参考资料 ​

工程实践与社区文章 ​