题干与适用场景
一个企业服务希望让持有授权密钥的客户端访问特定资源,同时不让未认证客户端通过 401 或 challenge 探测出资源存在。团队考虑 IETF RFC 9729(2025 年 2 月,Standards Track),该方案用 TLS keying material exporter 生成与连接绑定的签名输入,客户端通过 Authorization: Concealed 发送证明。
请设计客户端、边缘网关和源站的部署,说明 48 字节导出结果、认证参数、TLS 版本限制、连接复用、密钥吊销、旧客户端回退和上线验证。RFC 9729 的 2026 年已验证勘误必须纳入实现审计。
面试官考察点
面试官看重你能否解释“隐藏认证能力”与“保证请求新鲜度”是两个不同目标:RFC 9729 不发送 challenge,但证明的新鲜度不超过底层 TLS 连接生命周期。
强回答还会覆盖前端网关如何安全转发 Concealed-Auth-Export、密钥不可跨协议复用、HTTP/2/3 多路复用隔离、撤销缓存一致性、回退路径和误配置诊断,而不是只背出几个 header 名称。
回答前需要澄清的问题
- 客户端密钥由谁签发、每个 origin 是否独立,是否支持短期密钥?
- 网关和源站是否拆分,二者如何传递 TLS exporter 输出?
- 资源访问需要连接级新鲜度还是每个请求级新鲜度?
- 旧客户端只支持 TLS 1.2 时是否协商 Extended Master Secret?
- 授权撤销需要秒级生效,还是允许缓存窗口?
30 秒回答框架
“我会先按 origin 和 realm 建立公钥目录,客户端在 TLS 连接上用 RFC 9729 指定的 exporter 计算 48 字节输出并签名,网关只解析和转发合规参数,源站负责最终验签和授权。TLS 1.3 默认满足绑定要求,TLS 1.2 必须确认 Extended Master Secret,否则按未认证处理。密钥轮换采用双读单写和短缓存,撤销优先于缓存;连接级证明不能冒充请求级新鲜度。灰度期间记录参数解析、验签、撤销和回退原因,异常时关闭新 scheme 而不暴露资源状态。”
分步骤深入解答
先建立密钥与 origin 目录
服务端为每个 origin 维护 key ID 到公钥、算法、realm、签发时间和撤销状态的映射。客户端私钥只用于 Concealed 方案,不能复用到其他协议;RFC 9729 用固定签名前缀降低跨协议误用风险,但密钥隔离仍是部署责任。密钥 ID 不应编码用户隐私,审计日志使用不可逆内部标识。
计算连接绑定的证明
客户端必须使用 exporter label EXPORTER-HTTP-Concealed-Authentication、RFC 规定的上下文和 48 字节输出。前 32 字节进入签名输入,后 16 字节作为验证值发送;上下文包含算法、key ID、公钥、scheme、host、port 和 realm。任何字段编码不一致都会导致验签失败,不能由服务端“宽松解析”修复。
exported = TLS-Exporter(label, context, 48)
signature_input = exported[0:32] + domain_separation_prefix
verification = exported[32:48]
Authorization: Concealed k=..., a=..., s=..., p=..., v=...设计网关与源站边界
单体源站可以直接读取 TLS exporter。网关与源站拆分时,网关验证参数格式并通过 Concealed-Auth-Export 传递 48 字节 exporter 输出;该字段必须只在受信任的内部链路出现,不能由公网客户端注入。源站仍需检查请求目标、算法、key ID、公钥和签名,网关验过格式不等于授权成功。
执行 TLS 与协议约束
RFC 9729 要求 TLS 1.3,或 TLS 1.2 且协商 Extended Master Secret。否则服务端必须把请求视为没有认证。HTTP/2 和 HTTP/3 的 TLS 绑定可以使用该机制,但连接级证明可能覆盖同一连接上的多个请求;客户端和网关必须隔离不同安全上下文,避免跨租户读取 Authorization 头。
处理新鲜度、复用与重放
导出器证明的新鲜度最多等于 TLS 连接寿命,并非每个 HTTP 请求独立。若资源要求更短窗口,服务端可要求客户端建立新连接,例如通过连接关闭或 HTTP/3 GOAWAY,再结合短期 key ID 和服务端时间策略。不要把 v 参数当作请求 nonce,也不要在不验证 host、port、realm 的情况下接受同一签名。
轮换、撤销与回退
密钥目录采用双读单写:先发布新公钥并允许旧 key ID 短时间验证,再切换客户端,最后撤销旧 key。撤销检查应在授权决策前完成,缓存必须有明确 TTL 和失效通道。旧客户端可回退到既有认证,但回退响应要保持外部状态一致,不能用不同 401 文案泄露资源是否存在。
观测与故障定位
分层统计参数解析失败、TLS 不满足、key ID 未知、公钥不匹配、签名失败、撤销命中、网关转发失败和回退率。按 origin、客户端版本、协议和算法分组,但不要记录私钥、完整签名或可关联的用户密钥。勘误审计要覆盖 RFC 9729 第 3.3 节上下文字符串和第 4 节整数 ABNF,避免实现与修订后的规范不一致。
灰度与安全测试
先对一个 origin 和可撤销的低权限资源开启,验证 TLS 1.3、TLS 1.2+EMS、HTTP/2、HTTP/3、网关拆分和连接重建。注入错误 host、port、realm、算法、key ID、导出长度、重复 header、过期撤销缓存和跨租户连接,确认均按未认证处理。回滚只停止签发新密钥和接受新 scheme,保留旧目录与审计记录,避免把失败请求变成可探测的状态差异。
高质量示范回答
“RFC 9729 是连接绑定的不可探测认证,不是每请求 nonce。客户端按规范构造 exporter context,得到 48 字节输出并用专用密钥签名;网关只做参数解析和受信任的 exporter 转发,源站验证 TLS 条件、目标字段、key ID、公钥、签名、撤销和授权。TLS 1.3 或 TLS 1.2+EMS 才能接受,否则按未认证处理。密钥按 origin 隔离、双读单写轮换,短新鲜度需求通过重建连接实现。灰度监控解析、验签、撤销和回退,回滚停止新 scheme 并保持外部错误形态一致。”
常见错误
- 把 exporter 当每请求 nonce → 长连接上的证明可复用 → 明确连接级新鲜度,必要时重建连接。
- 只在网关验签 → 源站可能信任伪造的内部头 → 源站仍验证上下文与授权。
- TLS 1.2 未确认 EMS 也接受 → exporter 绑定不足 → 不满足条件按未认证处理。
- 密钥跨协议复用 → 跨协议签名混淆 → 每个方案和 origin 使用独立密钥。
- 撤销结果长时间缓存 → 已撤销客户端继续访问 → 明确 TTL、失效通道和优先级。
- 回退返回不同资源错误 → 暴露资源是否存在 → 统一外部状态,内部记录原因。
追问及应对
追问一:为什么不让源站主动发 challenge?
主动 challenge 会让未认证客户端观察到资源需要认证,破坏不可探测目标。RFC 9729 通过 TLS exporter 取得与连接绑定的新鲜材料,客户端可以主动发送证明。
追问二:48 字节为什么拆成 32 和 16?
规范把前 32 字节作为签名输入,后 16 字节随请求发送以便服务端确认 exporter 输出正确。实现必须按字节范围处理,不能把整个 48 字节直接当作 nonce。
追问三:网关把 exporter 转发给后端安全吗?
只有在网关到后端的受信任、完整性保护链路上才安全。公网客户端可伪造同名 header,因此网关必须覆盖或剥离外部值,后端还应校验内部通道身份和字段长度。
追问四:如何应对已建立连接上的密钥撤销?
撤销检查在每次授权决策执行,不能只在连接建立时检查。若风险要求更强的新鲜度,可撤销旧 key、发送连接关闭信号并要求客户端用新 key 建立连接。