每次你登录一个网站,系统至少要处理四个不同问题:
- 身份解析:这个账户、设备或工作负载由哪个稳定标识表示?
- 身份校验:申请者是否控制已登记的验证器?(Authentication,AuthN)
- 授权决策:此主体能否对这个资源执行这个动作?(Authorization,AuthZ)
- 会话与审计:这次决定何时失效,发生了什么,能否撤销和追查?
身份核验(identity proofing)还要回答“这个数字账户与哪个现实主体有关”,它不同于每次登录。一个系统可以正确验证账户控制权,却仍因对象级授权错误让用户读取他人数据。
威胁模型:真正被攻击的是整条身份生命周期
需要保护的资产包括账户控制权、会话、恢复渠道、权限、审计记录和个人属性。攻击者可能钓鱼、填充撞库、劫持短信、窃取浏览器令牌、注册恶意 OAuth 客户端、滥用内部权限,或直接攻陷身份提供方。
因此控制必须覆盖注册、验证器绑定、登录、提权、联合身份、恢复、权限变更、离职和撤销。只在登录页加 MFA,无法修复一个只靠安全问题即可重置密码的恢复流程。
破除误解:密码不是最佳身份验证
密码是数字世界最普遍的身份验证机制,也是最脆弱的一个。问题不在于密码的概念,而在于人类使用密码的方式:
- 在多个网站复用相同密码(一处泄露,处处危险)
- 使用易猜的密码("123456"每年都是最常用密码)
- 把密码写在便利贴上(绕过所有技术防护)
还有两条流传更广的"安全常识"其实早已被标准制定者否定:强密码必须混合大小写、数字和符号,以及每隔几十天就强制更换。
美国国家标准与技术研究院(NIST,National Institute of Standards and Technology)在 2017 年的《数字身份指南》中明确反对这两条做法,并在 2025 年 7 月定稿的第 4 版(SP 800-63B-4)里再次重申。
理由是:强制复杂度只会逼出"Password1!"这类可预测的变体,强制定期更换则让人把"Summer2024"改成"Summer2025",安全收益甚微。新标准转向长度优先——单因子使用的密码至少 15 个字符,鼓励易记的长口令句(passphrase),不到有泄露证据就不强制更换。
更根本的问题是:密码是一种"你知道什么"(something you know)的验证方式,只有一个因子。
多因素认证(Multi-Factor Authentication,MFA) 要求同时提供至少两种不同类型的凭据:
| 类型 | 示例 |
|---|---|
| 你知道什么(Knowledge) | 密码、PIN |
| 你拥有什么(Possession) | 手机、硬件安全密钥(YubiKey) |
| 你是什么(Inherence) | 指纹、人脸识别 |
但"第二个因子"之间强弱悬殊。最常见的短信验证码(SMS OTP)其实相当脆弱:攻击者可以用"SIM 卡交换"(SIM swap,冒充机主向运营商补办手机卡)把验证码截走。NIST 在 2025 年的新版指南里正式把短信列为"受限"(restricted)认证方式,要求继续使用它的机构必须向用户提示风险并提供替代方案。
更可靠的是验证器 App 生成的动态码:基于 RFC 6238 的 TOTP(Time-based One-Time Password,基于时间的一次性口令)用设备与服务器共享的密钥加上当前时间,算出每 30 秒变化的 6 位数字,全程无需联网。
MFA 通常显著提高批量攻击成本,但不能用一个跨场景固定百分比描述效果。TOTP 和短信验证码仍可被实时钓鱼代理转发;推送确认会遭遇 MFA fatigue;会话 cookie 在认证完成后被窃取,也可能绕过登录步骤。NIST SP 800-63B-4 因此把抗钓鱼性单独列为属性:手工输入的一次性代码不具备验证者名称绑定。
身份验证的技术实现
密码哈希与加盐
正确的密码存储方式是绝不存储明文密码,存储其密码学哈希。但直接哈希仍有漏洞:攻击者可以预先计算所有常见密码的哈希(彩虹表,Rainbow Table)。
解决方案是为每个密码生成唯一随机盐,再使用专用、可调成本的密码派生函数。盐阻止攻击者把一次预计算摊销到全部账户,但不会阻止对单个哈希继续猜常见密码。
推荐的密码哈希算法不是 SHA-256(速度太快,可以暴力破解),而是专门设计为慢速的: - bcrypt(1999):内置成本因子,可以随硬件提升调整计算量 - Argon2(2015):密码哈希竞赛冠军,抗 GPU 并行攻击,OWASP 推荐首选
一个常被忽视的坑:bcrypt 因底层 Blowfish 算法的结构,只对密码的前 72 个字节生效,多出的部分被静默丢弃——两个仅在第 72 字节之后才不同的长密码,会被当成同一个;Argon2 没有这个限制。
会话管理与 Cookie
HTTP 协议是无状态的——每个请求独立,服务器不记得之前的请求。如何维持登录状态?
会话(Session):登录成功后,服务器生成一个随机的会话 ID,返回给客户端(通常通过 Cookie),客户端后续请求携带此 ID。服务器在内存或数据库中维护会话状态。
JWT(JSON Web Token)只是一种声明容器格式,可用 JWS 签名/MAC,也可用 JWE 加密;“使用 JWT”本身不是会话架构。自包含令牌可减少每次查询,但会带来过期前撤销、声明陈旧、密钥轮换、iss/aud/算法验证和日志泄露问题。短寿命访问令牌、刷新令牌轮换、令牌内省或撤销列表可改变这些权衡。
浏览器会话还需要 Secure、HttpOnly、合适的 SameSite、会话 ID 轮换、空闲/绝对超时与 CSRF 防护。退出登录只删除前端状态而未让服务端会话失效,不算完整撤销。
Kerberos:早于 Web 的身份验证
身份验证不是随着网页登录框才出现的。1988 年,麻省理工学院(MIT)为校园计算环境 Project Athena 开发了 Kerberos,它建立在 Roger Needham 与 Michael Schroeder 1978 年提出的对称密钥认证思想之上。
Kerberos 引入一个可信第三方——密钥分发中心(Key Distribution Center, KDC)——来签发有时限的"票据"(ticket)。用户只登录一次,换得一张"票据授予票据",之后访问各个服务时凭它再换取服务票据,密码本身从不在网络上传输。
这套机制至今仍是 Windows 域(Active Directory)的默认登录协议,支撑着全球企业每天数以十亿计的登录。它的名字取自希腊神话中守卫冥界之门的三头犬刻耳柏洛斯(Cerberus),三个头常被用来比喻认证涉及的三方:客户端、服务器与 KDC。
OAuth 2.0:授权的工业标准
你是否使用过"用 Google 账号登录"或"用 GitHub 账号登录"?这背后是 OAuth 2.0 协议(2012)。
OAuth 解决的问题:在不共享密码的情况下,让第三方应用访问你的资源。
四个角色: - 资源所有者(Resource Owner):你(用户) - 客户端(Client):第三方应用(如某个使用 GitHub 登录的网站) - 授权服务器(Authorization Server):GitHub 的 OAuth 服务器 - 资源服务器(Resource Server):GitHub 的 API
授权码流程: 1. 你在第三方应用点击"用 GitHub 登录" 2. 跳转到 GitHub 的授权页面,GitHub 询问你是否允许该应用访问你的某些信息 3. 你同意后,GitHub 返回授权码(Authorization Code)给第三方应用 4. 第三方应用用授权码换取访问令牌(Access Token) 5. 第三方应用用令牌调用 GitHub API,获取你的用户信息
关键点:第三方应用始终不知道你的 GitHub 密码。你可以随时在 GitHub 设置中撤销该应用的访问权限。
OpenID Connect(OIDC):建立在 OAuth 2.0 之上,专门用于身份认证(OAuth 本身只定义了授权)。OIDC 在 OAuth 的访问令牌之外,还提供了 ID Token(包含用户身份信息的 JWT),成为"用 xxx 账号登录"功能的标准实现。
OAuth 早期还有一个"隐式流程"(implicit flow),允许单页应用和手机 App 直接从重定向 URL 里取得令牌,但令牌会残留在浏览器历史和服务器日志中,容易泄露。
2015 年的 PKCE(Proof Key for Code Exchange,RFC 7636)把授权请求和换取令牌的客户端实例绑定。2025 年 OAuth 安全最佳实践 RFC 9700 已弃用隐式流程,并要求重定向 URI 精确匹配、避免开放重定向,对所有客户端采用 PKCE。
这些参数不能混用:
state把授权响应绑定到发起它的浏览器事务,并可用于 CSRF 防护;- PKCE 的
code_verifier防止截获或注入的授权码被其他实例兑换; - OIDC
nonce把 ID Token 绑定到认证事务并防重放; iss、aud、签名、过期时间和授权服务器元数据验证令牌来源及接收者。
访问令牌若是 bearer token,持有者通常即可使用。发送者约束机制可以进一步把令牌绑定到客户端密钥,但仍不替代最小 scope、短寿命和资源服务器的 audience 校验。
授权模型
基于角色的访问控制(RBAC,Role-Based Access Control):把权限分配给角色,把角色分配给用户。例:管理员角色有所有权限,普通用户只有读权限。简单,适合用户角色明确的系统。
基于属性的访问控制(ABAC,Attribute-Based Access Control):根据多种属性(用户属性、资源属性、环境属性)动态决定访问权限。例:"销售部门的员工,在工作时间,可以访问当前季度的销售数据"。灵活,适合复杂场景,但实现和维护更复杂。
基于策略的访问控制(PBAC):用声明式的策略语言(如 AWS IAM Policy、Open Policy Agent)描述访问控制规则,集中管理。
无论使用哪种模型,都需要把策略决策点和每一个策略执行点连起来。常见缺陷不是缺少 RBAC,而是某个 API、批量导出、缓存、后台任务或对象存储绕过了检查。稳健基线包括默认拒绝、服务端逐对象校验、租户边界、最小权限、职责分离、临时授权和可复核的决策日志。
授权测试不能只问“管理员能否成功”。还要验证横向越权、纵向越权、撤销后的旧会话、批量接口、间接对象引用和失败时默认行为。策略版本应与部署制品一起审查和回滚。
无密码认证的未来
FIDO2 / WebAuthn用公钥密码学实现抗钓鱼认证。验证器为特定 relying party ID 创建凭据,登录时对服务器挑战和 origin 等上下文签名。私钥可能是硬件绑定凭据,也可能作为 passkey 在受保护的同步生态中跨设备恢复,不能一概声称永远不离开单台设备。
其抗钓鱼性主要来自验证器对 RP ID/origin 的绑定,而不是要求用户辨认假网站。服务器保存公钥,数据库泄露不能直接生成签名;但账户恢复、设备同步账户、注册新验证器和端点恶意软件仍在信任边界内。
代价与争议
恢复是旁路登录:备用码、客服、邮箱、电话号码和受信设备都可能成为攻击者的最短路径。恢复强度应与主认证相称,敏感操作还需重新认证、延迟、通知或多人批准。
OAuth 的滥用:OAuth 定义委托授权,不直接定义登录语义。“用某账号登录”应使用 OIDC 并验证 ID Token。state缺失会引入事务绑定/CSRF问题;未验证 aud 则可能接受原本发给另一个客户端或资源服务器的令牌,两者不是同一缺陷。
生物特征不是秘密字符串:它通常用于在本地激活验证器,还需活体检测、错误率、无障碍与替代路径。模板泄露难以撤销,集中收集还会增加 privacy-engineering 风险。
跨域连接
- Web 安全:跨站请求伪造是混淆代理问题的浏览器版:浏览器自动附带 cookie,服务端因此无法区分"用户想做"与"某个页面让浏览器做"。缺的不是身份而是意图,所以对策落在 SameSite 与一次性令牌上。同理,只在登录页加多因素,修不了一条靠安全问题就能重置密码的恢复流程。
- 服从权威:推送式二次确认会退化成顺从——被反复打扰后,用户点"同意"只是为了终止打扰,而不是做了判断。因此抗钓鱼必须做进协议:验证器把凭据绑定到来源域,用户认不认得出假网站就不再重要。由此可推:手工输入的一次性代码仍会被实时钓鱼代理转走,因为它没有绑定验证者名称。
- 问责:认证只证明"某人控制了验证器",问责却要求把行为绑到可追责的主体上。这条落差解释了为什么审计日志、会话撤销与恢复流程的强度,往往比密码规则更决定事后能不能查清。常见缺陷也不是缺少角色模型,而是某个批量接口或后台任务绕过了检查点。
- 数字身份:最小披露与可追责天然对立,披露越少越难追责。零知识证明把这条对立从全有全无变成可切分——只证明"已满十八岁"而不交出生日,让身份属性能够逐条被验证而不被收集。代价是验证方要接受更复杂的证明与更长的信任链。
- 基因检测与隐私:密钥可以轮换,虹膜和指纹不能。生物特征模板一旦泄露就永久失效,与基因数据同构;这决定了它更适合在本地激活验证器,而不适合当作跨系统共享的秘密集中存储。工程上的对策是把它当作本地凭据的开关,而不是当作一段可以传输的口令。
参考文献
- Hardt, D. The OAuth 2.0 Authorization Framework. RFC 6749, IETF, 2012.
- Recordon, D. & Reed, D. OpenID 2.0: A Platform for User-Centric Identity Management. ACM Workshop, 2006.
- NIST. Digital Identity Guidelines (SP 800-63-4). 2025.
- W3C. Web Authentication: An API for Accessing Public Key Credentials (WebAuthn). w3.org, 2019.
- OWASP. Authentication Cheat Sheet. cheatsheetseries.owasp.org.
- NIST. Digital Identity Guidelines — Authentication and Authenticator Management (SP 800-63B-4). 2025.(取消密码复杂度与定期更换要求,将短信列为受限认证)
- Steiner, J. G., Neuman, B. C. & Schiller, J. I. Kerberos: An Authentication Service for Open Network Systems. USENIX Winter Conference, 1988.
- Needham, R. M. & Schroeder, M. D. Using Encryption for Authentication in Large Networks of Computers. Communications of the ACM, 21(12), 1978.
- M'Raihi, D., Machani, S., Pei, M. & Rydell, J. TOTP: Time-Based One-Time Password Algorithm. RFC 6238, IETF, 2011.
- Sakimura, N., Bradley, J. & Agarwal, N. Proof Key for Code Exchange by OAuth Public Clients. RFC 7636, IETF, 2015.
- Lodderstedt, T. et al. Best Current Practice for OAuth 2.0 Security. RFC 9700, IETF, 2025.
- Hardy, N. The Confused Deputy (or why capabilities might have been invented). ACM SIGOPS Operating Systems Review, 22(4), 1988.
- W3C. Web Authentication: An API for Accessing Public Key Credentials Level 3. Candidate Recommendation.