安全防护、审计与运行保障
认证系统持续处理秘密、外部输入和账号控制权变化。防护措施需要对应具体攻击路径,并在依赖故障、缓存滞后和恢复过程中保持明确行为。
威胁与防线
| 威胁 | 发生条件 | 主要防线 |
|---|---|---|
| 撞库与密码猜测 | 攻击者批量提交候选凭据 | 多维限流、泄露密码拦截、MFA、验证并发限制 |
| 账号枚举 | 不同账号状态产生可区分响应 | 公开响应收敛、耗时分析、接口限流 |
| 会话固定或盗用 | 已知会话值被保留,或凭据泄露 | 登录轮换、HTTPS、秘密隔离与撤销 |
| CSRF | 浏览器自动携带凭据,攻击者能诱发请求 | CSRF Token、来源校验、SameSite 与接口约束 |
| XSS | 不可信内容在本站执行 | 上下文输出编码、安全模板、必要的 HTML 清洗 |
| OAuth 登录混淆 | 回调未关联正确浏览器和提供方 | 事务绑定、PKCE、state、issuer 与令牌校验 |
| 越权与跨租户访问 | 已登录主体访问其他资源 | 对象级授权、租户约束和批量范围检查 |
| 恢复入口接管 | 弱恢复路径绕过强认证 | 单次凭据、版本约束、强证明与通知 |
威胁表是检查入口,不能代替各流程的状态与事务设计。
CSRF:自动携带凭据的代价
Cookie 登录下,浏览器可能在攻击者诱导的请求中携带本站凭据。因此修改邮箱、退出、绑定认证器、刷新登录等状态变更也需要防护,不仅是支付接口。
OWASP CSRF Prevention讨论同步 Token、签名双重提交和来源校验。自有网站可优先使用框架提供的、绑定会话的 CSRF 机制;状态变更使用合适的非 GET 方法,同时精确检查受信来源。
- Token 从受保护页面或端点取得,在请求头或表单中提交,不放入容易被日志记录的 URL。
- 缺失或
null的 Origin 不能直接判定为安全;要由其他有效防护或受控策略决定。 - SameSite 是额外限制,不覆盖所有同站子域和导航场景。
- CORS 允许列表不能无条件反射请求 Origin,携带凭据时更要精确配置。
使用显式 Bearer Header 的客户端通常不会被浏览器自动附加该凭据,但 Refresh Token 若放在 Cookie 中,刷新端点仍需独立分析。切换成 JWT 本身不会消除 CSRF。
XSS:HttpOnly 之后仍有风险
HttpOnly 能减少脚本直接读取 Cookie 的机会,但恶意脚本仍可能利用当前会话读取数据、修改资料或发起敏感操作。防护重点是让不可信内容无法成为可执行代码。
按 OWASP XSS Prevention对 HTML、属性、URL 等不同上下文采用合适编码;确需展示富文本时,使用维护中的清洗库。不要把输入过滤当作所有输出上下文的通用替代。
CSP可以进一步约束脚本执行与资源来源,但需要结合实际页面部署与报告逐步验证。它是补充防线,不能用一段宽松策略覆盖 innerHTML、第三方脚本和不安全模板造成的问题。
认证与恢复页面尽量减少第三方脚本。错误收集、埋点、浏览器扩展和截图也可能获取敏感内容;日志脱敏不能只覆盖服务器端。
凭据传输与代理边界
RFC 6750说明 Bearer Token 的持有者可以使用它,应通过受保护传输和规范化载体传递,避免 URL 暴露。对自有 API,优先使用 Authorization: Bearer ...,不在普通查询参数中放访问令牌。
TLS 终止代理之后的链路同样需要受保护。应用只信任已配置代理写入的协议、地址和身份头,清除来自外部的同名头;否则来源校验、限流和安全跳转可能都受伪造输入影响。
会话凭据、Authorization、密码、验证码、恢复链接、TOTP 种子和 Refresh Token 均不进入普通日志。代理、APM、消息队列和错误上报的默认采集也要检查。
安全审计事件
OWASP Logging强调事件需要解释何时、何地、何人、发生了什么。建议采用结构化事件,而不是仅记录“登录接口返回 200”。
{
"event_id": "evt_01",
"event_type": "auth.session.revoked",
"occurred_at": "2026-10-30T08:00:00Z",
"actor_user_id": "user_123",
"subject_user_id": "user_123",
"tenant_id": null,
"session_id": "sess_public_456",
"reason": "password_reset",
"result": "success",
"request_id": "req_789"
}这里的 session_id 是管理标识,不是可登录的会话凭据。失败登录中对账号是否存在的内部标记应限制访问;不存在账号的标识可以按隐私策略使用受控摘要,而不是长期保存原始输入。
需要审计登录成功与失败、绑定与解绑、密码重置、MFA 更换、刷新重用、退出、封禁、角色修改和客服恢复。管理员代操作同时记录操作者和被操作主体。
关键安全变更与 outbox 事件可在同一事务提交,降低“变更成功但事件丢失”的概率。审计消费者需要去重与受限重试;日志本身设置访问控制、保留策略、完整性保护和导出审批。
依赖故障如何处理
| 故障 | 建议的受控行为 |
|---|---|
| 会话或账号权威状态不可查询 | 受保护操作失败,返回可重试的服务错误 |
| JWKS 刷新失败 | 已知且仍受信的缓存密钥按策略使用,未知密钥拒绝 |
| 短信或邮件超时 | 记录发送状态,限频重试,避免重复收费与轰炸 |
| MFA 服务不可用 | 使用已登记备用方式或恢复流程,不自动跳过 |
| 事件总线积压 | 监控撤销延迟,敏感操作回查权威状态 |
| 审计下游不可用 | 关键事件先可靠落本地事务记录,不能无限吞掉失败 |
身份无效与依赖故障要在内部区分。依赖故障不应伪装成密码错误而诱导用户反复改密;客户端也不能对 401 无限刷新,形成请求风暴。
指标与告警
建议至少观察:
- 按认证方式与失败原因聚合的成功率、P95/P99 延迟。
- 哈希验证并发、内存、排队、被限流请求和验证码费用。
- OIDC 回调校验失败、未知密钥、刷新重用和恢复请求异常。
- 封禁到各服务拒绝旧会话的传播延迟。
- outbox 积压、目录同步延迟与单点退出失败。
用户 ID、邮箱、令牌与会话 ID 不作为指标标签,避免高基数和隐私泄露。告警还要考虑来源变化与误伤,失败数上升可能来自提供方故障,而不全是攻击。
验证与恢复演练
安全验证需要同时覆盖正常路径与绕过路径:
| 范围 | 必测场景 |
|---|---|
| 登录 | 不存在账号、错误密码、长输入、并发验证、限流误伤 |
| 一次性凭据 | 重复消费、到期边界、并发提交、旧安全版本 |
| 浏览器 | 跨站表单、错误 Origin、XSS 注入点、Cookie 属性 |
| OIDC | state/nonce/issuer 不匹配、重复回调、开放重定向 |
| 令牌 | 错误受众、算法替换、过期、刷新重放、密钥轮换 |
| 权限 | 跨租户、角色撤销、批量接口、后台任务 |
| 故障 | 会话库丢失、备份恢复、事件延迟、提供方停机 |
备份恢复后特别检查旧会话、旧恢复请求和旧角色是否“复活”。密钥泄露演练应实际验证所有验证方停止接受旧签名,而非只确认签发方已换密钥。
参考资料
- OWASP:CSRF Prevention Cheat Sheet
- OWASP:XSS Prevention Cheat Sheet
- OWASP:Content Security Policy Cheat Sheet
- OWASP:Logging Cheat Sheet
- IETF:RFC 6750 — OAuth 2.0 Bearer Token Usage
工程实践与社区文章
- 美团技术团队:前端安全系列(二):如何防止CSRF攻击?——跨站请求的攻击路径与 Token、来源校验等防护方式。
- 美团技术团队:前端安全系列(一):如何防止XSS攻击?——不同注入上下文中的攻击案例与输出处理。
- 美团技术团队:实践之后,我们来谈谈如何做好威胁建模——在设计阶段识别信任边界、攻击路径与安全需求。
- 美团技术团队:大众点评账号业务高可用进阶之路——账号业务的依赖治理与可用性建设。