关于设置的一些上下文:
我们正在从 NTLM 切换到 Kerberos (Negotiate),以便在各种 .NET 工作负载(例如 IIS 托管的 Web API 或简单的 .NET 命令行程序)之间进行服务到服务身份验证。
对于从客户端到服务器的任何调用,中间都有一个 API 网关。我们在网关中有一些自定义逻辑,用于进行身份验证和执行 Kerberos(拒绝使用 NTLM 票证的协商标头)。健康的客户端-服务器流程如下所示:
- 客户端(C) 向服务器(S)发送请求
- 网关(G)拦截请求
- (G) 使用WWW-Authenticate: Negotiate返回 401 质询
- (C) 再次发送请求,带有Authorization: Negotiate [ticket]标头
- (G) 检查[ticket]并且:
5.a 如果[ticket]是 NTLM:“拒绝”请求(返回非成功状态代码)
5.b 如果[ticket]是 Kerberos:验证票证并(如果有效)通过请求到 (S)
现在,为了不进行重大更改,我们能够(在网关中)配置(在网关中)应该发生此 Kerberos 检查的请求,基于来自 (C) 的请求的原始目标,这应该是大致的主机名和 (S) 的港口。
此设置工作正常,但偶尔会出现这个难以复制的问题:
- 有时,对于某些 (S),当我们在 (G) 中启用 Kerberos 签入时,客户端 (C) 会继续发送 NTLM 票证(因此被拒绝)。
- 尽管 (C) 能够与 (G) 对话 Kerberos 的所有先决条件都得到满足 - 例如
klist get HTTP/spn-of-G
,即使在模拟完全相同的用户时,也可以从 (C) 执行并接收正确的 Kerberos 票证。 (C) 通常会运行为 - 最重要的是,在与 (C) 相同的服务器上,通常还有其他应用程序可以很好地通过相同的流程
- 重新启动 (C) 正在运行的 Windows Server 实例可修复此问题,使 (C) 在重新启动后向 (G) 发送正确的 Kerberos 票证
我的问题是:在不重新启动服务器的情况下,是否还有其他可能解决这种情况?
我已经尝试过但没有成功的事情:
- 重新启动在 (C) 上运行的应用程序。如果 (C) 是 IIS 应用程序,我尝试重新启动应用程序池,或者
iisreset
. 但是我已经看到这个问题也发生了,例如,在 (C) 是一个 C# 命令行程序每 15 分钟运行一次的情况下。 - 在 (C) 运行的服务器上刷新 DNS,使用
ipconfig /flushdns
- 清除运行 (C) 的服务器上所有缓存的 Kerberos 票证(
klist purge
使用 powershell 脚本为所有登录会话执行)