Web 诞生之初没有“登录”这回事。要让服务器记住你是谁,才有了 Cookie;要让第三方应用访问你的数据,才有了 OAuth;要防钓鱼,才有了 Passkey。
一、Session + Cookie:把状态放在服务端
最经典的做法:用户提交账号密码,服务端创建会话,把 sessionId 写进 HttpOnly Cookie,后续请求带上它。
优点很明确:服务端可以随时让会话失效,也能清楚知道每个用户在做什么。
难点在于规模化:
- 多台服务器要共享会话(粘性会话或集中存储)
- 跨域场景下 Cookie 的
SameSite、Secure、Domain要配置正确 - 一旦 Cookie 泄露,攻击者就拥有了完整身份
二、JWT:把状态放到客户端
JWT 把用户标识和过期时间签名后交给客户端,服务端无需查存储即可验证。
它解决了“横向扩展时要共享会话”的问题,但被大量误用:
- 无法主动失效:签发后到过期前,令牌一直有效
- 把敏感信息塞进载荷:JWT 只签名,不加密
- 用长期令牌代替会话:泄露即长期失守
- 忽略算法校验:
alg: none之类的历史漏洞
合理用法是:短期访问令牌 + 可撤销的刷新令牌,并严格校验算法与受众。
三、OAuth 2.0 / OIDC:委托授权
OAuth 解决的是“如何让第三方在不知道你密码的前提下访问你的资源”。OIDC 在其上补了身份层(ID Token)。
落地时最容易出错的是回调与重定向:
redirect_uri必须严格白名单匹配,不能做前缀匹配state要防 CSRF,PKCE 要用于公共客户端- 授权码只能用一次,且必须服务端换取令牌
四、TOTP:第二因素的最低门槛
短信验证码有被拦截和 SIM 交换的风险,TOTP(基于时间的一次性密码)成本低、离线可用,是很多后台系统的默认选择。
它的局限也很清楚:不能防实时钓鱼。用户在假站点输入验证码,攻击者立刻用它登录。
五、Passkey / WebAuthn:把“共享秘密”换成密钥对
Passkey 的核心是:私钥留在设备的安全芯片里,服务器只保存公钥。登录时由设备签名一个挑战。
好处是:
- 没有可被拖库的密码
- 私钥不会被钓鱼站点骗走(绑定源站)
- 用户体验通常比输密码更快
代价是:
- 需要处理跨设备、跨生态的同步与恢复
- 老设备与部分浏览器的兼容
- 账号恢复流程必须重新设计(这是最容易出安全事故的地方)
六、无论用哪种,绕不开的三件事
- 限流与锁定:防撞库,防短信轰炸
- 会话固定与登出:登录后换新会话,登出要真正失效
- 恢复流程:恢复码、备用邮箱、人工审核,往往是整套系统的薄弱点
结语
认证方案没有“最新最好”,只有“和你的风险模型匹配”。对个人博客,TOTP 加长密码已经足够;对涉及资金的系统,Passkey 加设备指纹加风控才谈得上及格。
真正要警惕的,不是技术选型落后,而是把安全当成一次性配置。
评论 (0)