Kerberos 票据的生命周期并不是从输入密码那一刻开始、到退出登录结束这么简单。它涉及 KDC 签发 TGT、客户端携带 TGT 申请 ST、服务端验证 ST、客户端缓存和续期、最终过期或主动销毁等阶段。每个阶段都有独立的时间边界和失败条件,票据内部记录的起始时间、到期时间、续期上限和标志位共同决定了一张票据还能不能用。

一、从 AS-REQ 到 TGT:初始票据的诞生
客户端第一次访问 Kerberos 保护的服务时,会先向认证服务器发送 AS-REQ 请求。以 Windows 域或 MIT Kerberos 环境为例,该请求通常包含用户主体名和预认证数据。预认证数据的作用是向 KDC 证明客户端确实知道用户密码,而不是单纯拿用户名冒领票据。客户端使用用户长期密钥对时间戳加密,KDC 解密校验后才会进入签发流程。
AS-REP 返回两类关键信息:一是 TGT,二是随 TGT 一起下发的会话密钥。TGT 由 KDC 的 krbtgt 账户密钥加密,客户端无法解密 TGT 自身内容,因为客户端没有 krbtgt 密钥。TGT 对客户端来说更像一个不透明的令牌,它真正的价值是配合客户端掌握的会话密钥一起,在后续 TGS-REQ 中向 KDC 证明:这个用户在不久之前已经通过过一次完整身份验证,可以批量申请服务票据而不必反复输入密码。
可以使用 klist 命令查看当前缓存中的 TGT,输出会包含有效期和续期截止时间。例如下面这份凭证缓存显示 TGT 有效期是十小时,续期截止时间是七天。
Ticket cache: FILE:/tmp/krb5cc_1000 Default principal: user@EXAMPLE.COM Valid starting Expires Service principal 11/20 08:00 11/20 18:00 krbtgt/EXAMPLE.COM@EXAMPLE.COM renew until 11/27 08:00
理解这个阶段的关键在于区分长期密钥和会话密钥。长期密钥来自用户密码或 keytab 文件,只参与初始认证;会话密钥是和 TGT 绑定的短期密钥,用于后续请求。这样即使 TGT 在网络上被截获,攻击者没有会话密钥也无法直接利用,而会话密钥本身不会在 AS-REP 中明文出现。
二、TGT 与 ST 的有效期和续期边界
TGT 和 ST 虽然都叫票据,但生命周期差异很大。TGT 默认有效期通常是十小时,服务票据 ST 默认只有五分钟。这样设计是因为 TGT 代表用户身份,泄露后风险较高,但还需要平衡单点登录体验;ST 是访问具体服务的凭证,短有效期可以尽量避免服务端长时间依赖一张被截获的票据,同时用户在单次应用会话中即使 ST 过期,也可以凭仍然有效的 TGT 快速重新申请,不会频繁打断操作。
另一种容易忽略的边界是续期上限 renew-till。TGT 本身即使过期,只要当前时间没有超过 renew-till,客户端就可以使用 kinit -R 命令续期。续期时不需要重新输入密码,因为 KDC 主要检查 TGT 的标志位和 renew-till,而不是再次执行预认证。一旦超过 renew-till,这张 TGT 就彻底失效,客户端只能重新发起 AS-REQ。
| 票据类型 | 默认有效期 | 默认续期上限 | 加密密钥 |
|---|---|---|---|
| TGT | 10 小时 | 7 天 | krbtgt 账户密钥 |
| ST | 5 分钟 | 受 TGT 续期上限约束 | 目标服务密钥 |
在 MIT Kerberos 中,这些默认值可以在 krb5.conf 的 libdefaults 段调整。ticket_lifetime 控制初始票据有效期,renew_lifetime 控制最大续期时间。配置示例如下。
[libdefaults]
default_realm = EXAMPLE.COM
ticket_lifetime = 10h
renew_lifetime = 7d
forwardable = true
proxiable = true
rdns = false
Windows 域环境下,域控制器的组策略中也可以针对用户票据和服务票据配置不同的最长寿命。如果客户端解析到的策略值不一致,往往表现为同一账号在 Linux 主机上认证正常,而在 Windows 主机上票据提前过期或续期失败,这通常不是协议缺陷,而是策略覆盖导致。
三、票据续期、转发与缓存的真实过程
续期操作的核心命令是 kinit -R。它不会重新读取密码,而是从当前凭证缓存中取出 TGT 和会话密钥,向 KDC 发送 TGS-REQ 申请一张新的 TGT。KDC 会检查票据的 renewable 标志位、renew-till 时间和当前时间是否在允许窗口内。如果检查通过,客户端会收到新的 TGT 和新的会话密钥,原有缓存被替换。如果当前 TGT 已经彻底过期且超过 renew-till,续期会失败,并提示重新用密码初始化凭证。
除了续期,转发票据 forwardable 和代理票据 proxiable 也会影响生命周期管理。具备 forwardable 标志的 TGT 可以被转发到远程主机,例如用户通过 SSH 登录到一台服务器后,该服务器可以代表用户去申请其他服务的 ST。这个特性在多层跳转场景中很方便,但也会延长凭证的间接使用范围。管理员需要明确策略:是否允许 TGT 被转发,以及转发后目标主机是否能安全保管凭证缓存。
客户端凭证缓存的生命周期与 TGT 生命周期并不完全相同。kdestroy 可以立即删除当前缓存文件,但已经派生的 ST 副本可能仍残留在应用进程内存中。某些 Java 或浏览器进程在启动时读取一次凭证缓存,之后不会自动刷新。因此即使命令行 klist 正常,应用仍可能因为内部缓存过期而拒绝访问。遇到这种情况,优先确认应用是否支持动态刷新凭证,或先退出应用再重新启动。
四、过期、时钟偏差与排障思路
票据过期的报错通常有明确提示,例如 TGT expired 或 ST expired。此时第一反应不是怀疑密码错误,而是用 klist 查看 Expires 字段。若 TGT 仍有效但 ST 过期,可以尝试通过重新调用 GSSAPI 初始化安全上下文来触发新的 TGS-REQ,应用程序通常会自己处理,但如果应用缓存了失效 ST,则需要清理进程缓存或重启服务。
时钟偏差是 Kerberos 环境中最常被忽视的失败原因。KDC 会校验请求中的时间戳与自身时间的差值,默认允许偏差为五分钟。如果客户端时钟比 KDC 快或慢超过五分钟,AS-REQ 或 TGS-REQ 都可能被拒绝,返回 KRB_AP_ERR_SKEW。排查时不要只看票据有效期,要同时检查客户端、KDC、目标服务三台机器的时间是否一致,并部署 NTP 同步。
klist -f kinit -R kdestroy
最后还要留意凭证缓存文件的权限。Linux 下默认缓存文件通常位于 /tmp/krb5cc_uid,权限设置为 600,仅当前用户可读。如果缓存文件被其他进程覆盖或权限被改宽,klist 可能读取失败,或在切换用户后拿到错误的凭证。良好的生命周期管理不只要关注 KDC 签发了什么,也要关注客户端如何保存和清理这些短期秘密。
Kerberos票据TGTST修改时间:2026-10-03 02:32:23