一、认证凭据选择:从"有密码"到"无密码"
2026 年的安全基线已经发生本质变化。认证凭据的选择决定了后续所有安全措施的有效性,一旦选错,后面的加固往往事倍功半。
首选方案:Passkey(FIDO2/WebAuthn)
Passkey 的核心设计是"私钥永不离开设备,服务端只存公钥"。私钥被绑定到特定域名(Origin Binding),钓鱼网站即使界面做得一模一样,也无法调用正确域名的私钥完成签名。数据显示,Passkey 可将钓鱼攻击成功率降至接近零,账户劫持风险降低 99% 以上。
次选方案:社交登录(OAuth 2.1 + PKCE)
对于不想管理凭据的系统,通过标准 OAuth 2.1 流程接入可信身份提供商,使用 PKCE 防止授权码拦截攻击。
遗留密码体系的底线要求
如果业务必须保留密码,必须强制启用多因素认证(MFA/2FA)。2024 年网络安全报告估计,超过 61% 的泄露事件涉及凭据被盗,而 MFA 是最有效的缓解手段。优先使用 TOTP(基于时间的一次性密码)或硬件安全密钥作为第二因素,禁止将 SMS 短信作为唯一的第二因素------SIM 卡交换攻击已非常成熟。
二、密码安全存储与策略
哈希算法选择
永远不要自己实现密码哈希。使用经过充分验证的算法:
- Argon2id(首选,抵抗 GPU/ASIC 破解)
- bcrypt(经典选择,工作因子 ≥ 12)
- scrypt(内存困难型,适合特定场景)
绝对禁止使用 MD5、SHA-1、SHA-256 等快速哈希算法存储密码,也禁止明文或可逆加密存储。
密码策略:长度优于复杂度
- 最小长度 12--16 位,而非强制大小写+数字+符号的组合规则。过复杂的规则反而导致用户复用密码或写下密码。
- 集成 Have I Been Pwned API 或类似服务,在注册/修改密码时检查密码是否出现在已知泄露库中,如果是则直接拒绝。
- 不提供"密码提示"功能,这是社会工程学的突破口。
三、注册流程安全
1. 防批量注册与滥用
攻击者会批量创建账号用于薅羊毛、发送垃圾信息或作为后续攻击的跳板。
- 速率限制 :按 IP 地址和按邮箱域名双重限制注册频率。例如,同一 IP 每小时最多 3 次注册,同一邮箱域名(如
tempmail.com)触发额外审核。 - 验证码:在注册环节部署图形验证码或行为验证码(如 hCaptcha / reCAPTCHA v3),但不要过度干扰正常用户。
- 邮箱/手机验证:注册后必须验证联系方式才能激活账号,防止使用一次性临时邮箱。
2. 防账号枚举
当用户尝试注册已存在的邮箱时,不要明确提示"该邮箱已注册"。统一返回模糊的提示,如"如果该邮箱未被使用,验证邮件已发送"。这能防止攻击者通过注册接口批量探测系统中存在的有效账号,进而针对性实施撞库攻击。
3. 输入验证
所有注册字段必须在服务端做严格的白名单校验:类型、长度、格式、范围。拒绝一切不符合预期的输入,这是防御注入攻击的第一道防线。
四、登录流程安全
1. 速率限制与账户锁定
登录接口是撞库攻击(Credential Stuffing)和暴力破解的首要目标。2020 年全球撞库攻击尝试已超过 1930 亿次。
- 对登录接口实施指数退避的速率限制:按 IP 地址和按账号分别计数。例如,同一账号连续 5 次失败则锁定 15 分钟,同一 IP 每分钟超过 10 次尝试则要求验证码或临时封禁。
- 记录所有失败登录尝试,用于后续风险分析。
2. 多因素认证(MFA)
对于敏感账户或全站强制:
- 注册 TOTP(如 Google Authenticator、Authy)时提供备用恢复码,并提醒用户妥善保存。
- 对高权限角色(管理员、财务)强制要求硬件安全密钥或 Passkey。
3. 设备指纹与风险自适应
在登录时采集设备指纹(Canvas、WebGL、字体列表等)和上下文信息(IP 地理位置、登录时间)。如果检测到异常(如平时在北京登录的用户突然从纽约尝试登录),触发阶梯式认证(Step-Up Authentication),要求额外验证。
五、会话与 Token 管理
这是登录安全中最容易出错的环节。OWASP 连续多年将"身份验证和会话管理不当"列为高危漏洞。
1. Cookie 安全属性
如果使用基于 Cookie 的会话,必须同时设置:
HttpOnly:禁止 JavaScript 读取,防御 XSS 窃取。Secure:仅通过 HTTPS 传输。SameSite=Lax(或Strict):防御 CSRF。Lax在用户体验和安全性之间取得平衡,Strict更安全但可能影响从外部邮件链接跳转后的正常 POST 操作。
2. 双 Token 架构(Access + Refresh)
现代主流方案:
- Access Token:短命(5--15 分钟),包含用户身份和权限,用于 API 访问。
- Refresh Token :长命(数天至数月),仅用于换取新的 Access Token,不直接用于资源访问。
关键安全措施:
- Refresh Token 轮换:每次使用 Refresh Token 换取新令牌时,旧 Refresh Token 立即失效,同时颁发新的 Refresh Token。如果同一个 Refresh Token 被使用两次,立即吊销该用户的整个 Token 家族(Token Family),这意味着 Token 可能已被窃取。
- 服务端存储:Refresh Token 必须在服务端持久化(如 Redis),这样才能实现即时吊销。Access Token 如果是 JWT,在过期前天然无法吊销,因此必须保持足够短的有效期。
- 竞态处理:在并发刷新场景下(如用户打开多个标签页),使用请求队列化或宽容窗口期,避免合法用户被误吊销。
3. 会话固定防护
攻击者可能预先获取一个未认证的 Session ID,诱骗用户使用该 ID 登录,从而劫持会话。登录成功后必须立即轮换 Session ID / 颁发新的会话 Cookie。
4. 吊销能力
必须支持以下场景的即时吊销:
- 用户主动登出 → 删除当前设备的 Refresh Token。
- 用户修改密码 → 删除该用户所有设备的 Refresh Token,强制重新登录。
- 管理员发现异常 → 可针对特定用户或设备吊销会话。
六、密码找回与重置
密码重置是攻击者最喜欢的入口之一,必须比登录本身更严格。
重置令牌设计
- 单次有效 :使用后立即失效,未使用也应在 15 分钟内过期。
- 强随机性:使用加密安全的随机数生成器(CSPRNG),长度至少 128 位熵,避免可预测性。
- 绑定用户:重置令牌必须只能用于重置颁发时对应的特定用户账号,防止篡改 UID 后重置他人密码。
- 安全投递:通过用户预先验证的邮箱或手机发送链接,绝不通过客服等人工渠道。
- 级联失效:密码重置成功后,立即吊销该用户的所有活跃会话和 Refresh Token。
防枚举
与注册同理,无论用户输入的邮箱是否存在,都显示相同的提示:"如果该邮箱存在于系统中,重置链接已发送"。
七、传输与基础设施安全
1. 全站 HTTPS
所有认证相关请求(登录、注册、密码修改、Token 刷新)必须使用 HTTPS/TLS 1.2 或更高版本传输。禁止任何情况下降级到 HTTP。
2. 安全响应头
部署以下 HTTP 安全头,作为纵深防御:
Content-Security-Policy:限制资源加载,防御 XSS。X-Frame-Options: DENY或Content-Security-Policy: frame-ancestors 'none':防御点击劫持。X-Content-Type-Options: nosniff:防止 MIME 嗅探。Strict-Transport-Security(HSTS):强制浏览器使用 HTTPS。Referrer-Policy:控制 Referrer 信息泄露。
3. 密码学实践
- 不自己造加密算法或协议,使用成熟的库。
- 对称加密用 AES-256-GCM,非对称用 RSA-2048+ 或 ECC。
- 密钥与加密数据分离存储,使用专业密钥管理服务(KMS)。
八、常见攻击防护速查
| 攻击类型 | 防御措施 |
|---|---|
| 撞库 / 凭证填充 | 登录速率限制 + 检测异常登录模式 + 强制 MFA |
| 暴力破解 | 账户锁定 + 验证码 + 密码最小长度 |
| 会话劫持 | HttpOnly Cookie + 短会话超时 + 定期轮换 Session ID |
| 会话固定 | 登录成功后立即更换 Session ID |
| CSRF | SameSite Cookie + 敏感操作附加 CSRF Token |
| XSS | 输出编码 + CSP + HttpOnly Cookie |
| SQL / NoSQL 注入 | 参数化查询 / ORM + 输入白名单校验 |
| 点击劫持 | X-Frame-Options / CSP frame-ancestors |
| 密码哈希泄露 | Argon2id / bcrypt + 加盐 + 定期算法升级 |
九、监控、日志与审计
没有监控的安全是盲目的。
必须记录的安全事件
- 登录成功/失败(含时间、IP、设备指纹、地理位置)。
- 密码修改、重置请求与完成。
- MFA 绑定/解绑。
- Refresh Token 重用事件(高度可疑,可能意味着 Token 被盗)。
- 异常登录行为(异地、频繁失败、非常用设备)。
日志安全
- 日志中绝不记录密码、明文 Token、密钥等敏感信息。
- 使用结构化日志,集中存储并设置防篡改机制。
- 建立告警规则,如"同一账号 10 分钟内从两个国家登录"触发即时通知。
十、开发者安全检查清单
凭据与认证
- 已支持 Passkey / WebAuthn(或已规划路线图)
- 保留密码的系统已强制启用 MFA(TOTP 或硬件密钥)
- 禁止 SMS 作为唯一第二因素
- 密码使用 Argon2id / bcrypt 存储,带独立盐值
注册
- 服务端白名单校验所有输入
- 注册速率限制(IP + 邮箱域名)
- 防账号枚举(模糊提示)
- 邮箱/手机验证后才能激活
登录
- 登录接口指数退避速率限制
- 登录成功后轮换 Session ID
- 设备指纹与风险自适应认证
会话管理
- Cookie 设置
HttpOnly; Secure; SameSite=Lax - Access Token 寿命 ≤ 15 分钟
- Refresh Token 每次使用后轮换
- Refresh Token 重用检测(二次使用即吊销全家桶)
- 支持用户级和设备级会话吊销
- 修改密码后强制全局重新登录
密码重置
- 重置令牌强随机、单次有效、15分钟过期
- 重置成功后吊销所有会话
- 防枚举处理
基础设施
- 全站 HTTPS(TLS 1.2+)
- 部署 CSP、HSTS、X-Frame-Options 等安全头
- 参数化查询防御 SQL 注入
- 敏感操作加 CSRF Token
监控
- 集中化安全日志,不含敏感数据
- Refresh Token 重用告警
- 异常登录行为告警
核心原则:安全不是单一措施,而是纵深防御(Defense in Depth)。即使某一层被突破,后续机制仍能阻止或延缓攻击。将安全左移(Shift Left),在设计和编码阶段就融入这些实践,远比上线后修补成本更低。