本文有助于在访问配置为在 Internet Explorer 中使用 Kerberos 身份验证的网站时隔离和解决各种错误的原因。 潜在问题的数量几乎与可用于解决这些问题的工具数量一样大。
Kerberos 失败时的常见症状
尝试访问已配置 Windows 集成身份验证的网站,并且你希望使用 Kerberos 身份验证协议。 在这种情况下,浏览器会立即提示输入凭据,如下所示:
虽然你输入了有效的用户名和密码,但系统会再次提示你(总共三个提示)。 然后,会显示一个屏幕,指示你不允许访问所需的资源。 屏幕显示类似于以下错误的 HTTP 401 状态代码:
未授权
HTTP 错误 401。 请求的资源需要用户身份验证。
在Microsoft Internet Information Services (IIS) 服务器上,网站日志包含以 401.2 状态代码结尾的请求,例如以下日志:
#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status time-taken
DateTime IP GET /whoami.aspx - 80 – IP Mozilla/4.0+(compatible;+MSIE+7.0;+Windows+NT+10.0;+WOW64;+Trident/7.0;+.NET4.0C;+.NET4.0E;+.NET+CLR+2.0.50727;+.NET+CLR+3.0.30729;+.NET+CLR+3.5.30729) - 401 2 5 1270
DateTime IP GET /whoami.aspx - 80 - IP Mozilla/4.0+(compatible;+MSIE+7.0;+Windows+NT+10.0;+WOW64;+Trident/7.0;+.NET4.0C;+.NET4.0E;+.NET+CLR+2.0.50727;+.NET+CLR+3.0.30729;+.NET+CLR+3.5.30729) - 401 2 5 8
或者,屏幕显示 401.1 状态代码,例如以下日志:
#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status time-taken
DateTime IP GET /whoami.aspx - 80 - IP Mozilla/4.0+(compatible;+MSIE+7.0;+Windows+NT+10.0;+WOW64;+Trident/7.0;+.NET4.0C;+.NET4.0E;+.NET+CLR+2.0.50727;+.NET+CLR+3.0.30729;+.NET+CLR+3.5.30729) - 401 2 5 105
DateTime IP GET /whoami.aspx - 80 - IP Mozilla/4.0+(compatible;+MSIE+7.0;+Windows+NT+10.0;+WOW64;+Trident/7.0;+.NET4.0C;+.NET4.0E;+.NET+CLR+2.0.50727;+.NET+CLR+3.0.30729;+.NET+CLR+3.5.30729) - 401 1 2148074245 18
确定是否使用 Kerberos
排查 Kerberos 身份验证失败问题时,建议将配置简化到最低。 也就是说,一个客户端、一台服务器和一个在默认端口上运行的 IIS 站点。 此外,还可以执行一些基本的故障排除步骤。 例如,使用测试页验证所使用的身份验证方法。 如果使用 ASP.NET,可以创建此 ASP.NET 身份验证测试页。
如果使用经典 ASP,可以使用以下Testkerb.asp页:
<%
authType=UCase(Request.ServerVariables("AUTH_TYPE"))
authHeader=Request.ServerVariables("HTTP_AUTHORIZATION")
response.write " Authentication Method : " & authType & "<BR>"
LenAuthHeader = len(authHeader)
response.write " Protocol : "
if Len(authType ) =0 then response.write " Anonymous" else if authType<>"NEGOTIATE" then response.write authType else if LenAuthHeader>1000 then response.write "Kerberos" else response.write "NTLM"
%>
还可以使用以下工具来确定是否使用了 Kerberos:
- Fiddler
- HttpWatch
- 网络监视器
- 浏览器中的开发人员工具
有关如何生成此类跟踪的详细信息,请参阅 客户端跟踪。
使用 Kerberos 时,客户端发送的请求很大(超过 2,000 字节),因为 HTTP_AUTHORIZATION
标头包含 Kerberos 票证。 以下请求适用于使用基于 Kerberos 的 Windows 身份验证对传入用户进行身份验证的页面。 GET 请求的大小超过 4,000 字节。
如果使用 NTLM 握手,则请求要小得多。 以下客户端捕获显示 NTLM 身份验证请求。 GET 请求要小得多(小于 1,400 字节)。
确定 Kerberos 身份验证失败后,按给定顺序检查以下每个项。
检查 Kerberos 身份验证是否失败的事项
以下部分介绍了可用于检查 Kerberos 身份验证是否失败的内容。
同一域中的客户端和服务器
使用 Kerberos 需要域,因为 Kerberos 票证由域控制器 (DC) 传送。 还可以在以下情况下使用高级方案:
- 客户端和服务器不在同一域中,而是位于同一林的两个域中。
- 客户端和服务器位于两个不同的林中。
这些可能的方案在 为什么 Kerberos 委派在我的两个林之间失败,尽管它用于本文的工作 部分。
IIS 是否配置为使用集成身份验证
在 Internet Explorer 中启用了集成身份验证
使用的 URL 是否解析为可以为其发送凭据的安全区域
始终针对以下站点运行此检查:
- 与浏览器的本地 Intranet 区域匹配的站点。
- 受信任的站点区域中的站点。
可以签入浏览器决定包含站点的区域。 为此,请打开 Internet Explorer 的“文件 ”菜单,然后选择“ 属性”。 “ 属性” 窗口将显示浏览器决定在其中包含要浏览到的网站的区域。
可以检查包含站点的区域是否允许自动登录。 为此,请打开 Internet Explorer 的 Internet 选项 菜单,然后选择“ 安全 ”选项卡。选择所需区域后,选择 “自定义级别 ”按钮以显示设置,并确保 已选择“自动登录 ”。 (通常,默认情况下,对于 Intranet 和受信任的站点区域,此功能处于打开状态)。
注意
即使通过此配置并不常见(因为它要求客户端有权访问 DC),Kerberos 也可用于 Internet 区域中的 URL。 在这种情况下,除非更改默认设置,否则浏览器将始终提示用户输入凭据。 Kerberos 委派在 Internet 区域中不起作用。 这是因为 Internet Explorer 仅允许 Kerberos 委派 Intranet 和受信任的站点区域中的 URL。
配置为发送 WWW-Authenticate: Negotiate 标头的 IIS 服务器
如果 IIS 未发送此标头,请使用 IIS 管理器控制台通过 NTAuthenticationProviders 配置属性设置 Negotiate 标头。 有关详细信息,请参阅 Windows 身份验证提供程序 <提供程序>。 可以通过 IIS 管理器中 Windows 身份验证详细信息的提供程序设置访问控制台。
注意
默认情况下, 未设置 NTAuthenticationProviders 属性。 这会导致 IIS 同时发送 Negotiate 和 Windows NT LAN Manager (NTLM) 标头。
客户端和服务器是否安装在同一台计算机上
默认情况下,此配置中未启用 Kerberos。 若要更改此行为,必须设置 DisableLoopBackCheck
注册表项。 有关详细信息,请参阅 KB 926642。
客户端是否可以获取 Kerberos 票证
可以使用 Kerberos 列表 (KLIST) 工具验证客户端计算机是否可以获取给定服务主体名称的 Kerberos 票证。 在此示例中,服务主体名称(SPN)是 http/web-server。
注意
KLIST 是一种本机 Windows 工具,因为 Windows Server 2008 适用于服务器端操作系统,Windows 7 Service Pack 1 适用于客户端操作系统。
如果 Kerberos 票证请求失败,则不使用 Kerberos 身份验证。 可能会发生 NTLM 回退,因为请求的 SPN 对 DC 未知。 如果 DC 无法访问,则不会发生 NTLM 回退。
若要声明 SPN,请参阅以下文章:
配置 Internet Information Services 上托管的 Web 应用程序时,如何使用 SPN。
Web 服务器是否使用默认端口(80)
默认情况下,Internet Explorer 不包括 SPN 中用于请求 Kerberos 票证的端口号信息。 如果使用 IIS 在不同的端口和标识下托管多个站点,则可能是个问题。 在此配置中,Kerberos 身份验证仅适用于特定站点,即使已在 Active Directory 中正确声明所有 SPN 也是如此。 若要解决此问题,必须设置 FEATURE_INCLUDE_PORT_IN_SPN_KB908209
注册表值。 (请参阅 有关如何声明密钥的信息的 Internet Explorer 功能密钥 部分。此设置强制 Internet Explorer 在 SPN 中包含用于请求 Kerberos 票证的端口号。
Internet Explorer 是否使用预期的 SPN
如果使用别名(CNAME)访问网站,Internet Explorer 首先使用 DNS 解析将别名解析为计算机名称(ANAME)。 然后,计算机名称用于生成 SPN 并请求 Kerberos 票证。 即使 Internet Explorer 地址栏中输入的 URL 是 http://MYWEBSITE
,如果 MYWEBSITE 是 MYSERVER (ANAME) 的别名(CNAME),Internet Explorer 也会请求 HTTP/MYSERVER 的 SPN。 可以使用注册表项更改此行为 FEATURE_USE_CNAME_FOR_SPN_KB911149
。 (请参阅 有关如何声明密钥的信息,请参阅 Internet Explorer 功能密钥 。
网络监视器跟踪是检查与 Kerberos 票证关联的 SPN 的好方法,如以下示例所示:
- Http: Request, GET /whoami.aspx , Using GSS-API Authorization
Command: GET
- URI: /whoami.aspx
Location: /whoami.aspx
ProtocolVersion: HTTP/1.1
Accept: image/gif, image/jpeg, image/pjpeg, application/x-ms-application, application/xaml+xml, application/x-ms-xbap, */*
Accept-Language: en-US,en;q=0.5
UserAgent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)
Accept-Encoding: gzip, deflate
Host: web-server
Connection: Keep-Alive
- Authorization: Negotiate
- Authorization: Negotiate YIILcAYGKwYBBQUCoIILZDCCC2CgMDAuBgkqhkiC9xIBAgIGCSqGSIb3EgECAgYKKwYBBAGCNwICHgYKKwYBBAGCNwICCqKCCyoEggsmYIILIgYJKoZIhvcSAQICAQBuggsRMIILDaADAgEFoQMCAQ6iBwMFACAAAACjggRtYYIEaTCCBGWgAwIBBaEOGwxPREVTU1kuTE9DQUyiKjAooAMCAQKhITAfGwRIVFRQG
WhiteSpace:
- NegotiateAuthorization:
Scheme: Negotiate
- GssAPI: 0x1
- InitialContextToken:
+ ApplicationHeader:
+ ThisMech: SpnegoToken (1.3.6.1.5.5.2)
- InnerContextToken: 0x1
- SpnegoToken: 0x1
+ ChoiceTag:
- NegTokenInit:
+ SequenceHeader:
+ Tag0:
+ MechTypes: Prefer MsKerberosToken (1.2.840.48018.1.2.2)
+ Tag2:
+ OctetStringHeader:
- MechToken: 0x1
- MsKerberosToken: 0x1
- KerberosInitToken:
+ ApplicationHeader:
+ ThisMech: KerberosToken (1.2.840.113554.1.2.2)
- InnerContextToken: 0x1
- KerberosToken: 0x1
TokId: Krb5ApReq (0x100)
- ApReq: KRB_AP_REQ (14)
+ ApplicationTag:
+ SequenceHeader:
+ Tag0:
+ PvNo: 5
+ Tag1:
+ MsgType: KRB_AP_REQ (14)
+ Tag2: 0x1
+ ApOptions:
+ Tag3:
- Ticket: Realm: ODESSY.LOCAL, Sname: HTTP/web-server.odessy.local
+ ApplicationTag:
+ SequenceHeader:
+ Tag0:
+ TktVno: 5
+ Tag1:
+ Realm: ODESSY.LOCAL
+ Tag2: 0x1
+ Sname: HTTP/web-server.odessy.local
+ Tag3: 0x1
+ EncPart:
+ Tag4:
应用程序池标识是否与与 SPN 关联的帐户匹配
当 Kerberos 票证从 Internet Explorer 发送到 IIS 服务器时,票证将使用私钥进行加密。 私钥是用于与 SPN 关联的用户帐户的密码哈希。 因此,只有在此帐户下运行的应用程序才能解码票证。
以下过程是 Kerberos 身份验证算法的摘要:
Internet Explorer 使用输入到地址栏中的 URL 来确定 SPN。
SPN 通过安全支持提供程序接口 (SSPI) API (InitializeSecurityContext) 传递到负责 Windows 安全性的系统组件(本地安全机构子系统服务 (LSASS) 进程)。 在此阶段,可以看到 Internet Explorer 代码不实现任何代码来构造 Kerberos 票证。 Internet Explorer 仅调用 SSPI API。
LSASS 使用传入的 SPN 向 DC 请求 Kerberos 票证。 如果 DC 可以提供请求(已知的 SPN),则会创建 Kerberos 票证。 然后,它使用从与 SPN 关联的帐户的用户帐户密码哈希构造的密钥来加密票证。 然后,LSASS 将票证发送到客户端。 就 Internet Explorer 而言,票证是一个不透明的 Blob。
Internet Explorer 封装标头中
Authorization: Negotiate
由 LSASS 提供的 Kerberos 票证,然后将票证发送到 IIS 服务器。IIS 处理请求,并使用指定的主机标头将其路由到正确的应用程序池。
应用程序池尝试使用 SSPI/LSASS API 解密票证,并遵循以下条件:
如果票证可以解密,Kerberos 身份验证会成功。 所有与票证关联的服务(如果票证允许,则委托),等等都可用。
如果票证无法解密,则返回 Kerberos 错误(KRB_AP_ERR_MODIFIED)。 此错误是一般错误,指示票证在传输过程中以某种方式更改。 因此无法解密票证。 此错误也会记录在 Windows 事件日志中。
如果未显式声明 SPN,Kerberos 身份验证仅适用于以下应用程序池标识之一:
- Network Service
- ApplicationPoolIdentity
- 另一个系统帐户,例如 LOCALSYSTEM 或 LOCALSERVICE
但不建议使用这些标识,因为它们是安全风险。 在这种情况下,Kerberos 票证是使用在 Active Directory 中创建的默认 SPN 生成的(在本例中,IIS 正在运行的服务器)添加到域。 此默认 SPN 与计算机帐户相关联。 在 IIS 下,计算机帐户映射到网络服务或 ApplicationPoolIdentity。
如果应用程序池必须使用除列出的标识以外的标识,请声明 SPN(使用 SETSPN)。 然后将其与用于应用程序池标识的帐户相关联。 常见的错误是创建具有不同帐户的类似 SPN。 例如:
- SETSPN http/mywebsite UserAppPool1
- SETSPN http/mywebsite UserAppPool2
此配置不起作用,因为无法确定使用 UserAppPool1 或 UserAppPool2 密码来加密 http/mywebsite SPN 的 Kerberos 票证。 此配置通常生成KRB_AP_ERR_MODIFIED错误。 若要确定你是否处于此错误的重复 SPN 方案中,请使用以下文章中所述的工具:
为什么在 AD 2012 R2 和 AD 2016 中仍可以具有重复的 SPN
从 Windows Server 2008 开始,还可以使用 Windows 的更新版本的 SETSPN,以便在为目标帐户声明新的 SPN 时使用 setspn –X
命令检测重复的 SPN。 有关详细信息,请参阅 Setspn。
我们还建议查看以下文章:
即使 Kerberos 身份验证在 IIS 6 中有效,在 IIS 7 及更高版本中也失败
内核模式身份验证是在 IIS 7 中引入的一项功能。 它具有以下优点:
- 性能会提高,因为不再进行内核模式到用户模式的转换。
- Kerberos 票证解码是使用计算机帐户而不是应用程序池标识进行的。 通过此更改,可以在不同的标识下运行多个应用程序池,而无需声明 SPN。
警告
如果为特定用户帐户(也用作应用程序池标识)声明了 SPN,则内核模式身份验证无法解密 Kerberos 票证,因为它使用计算机帐户。 此问题在 Web 场方案中很常见。 此方案通常为 (虚拟) NLB 主机名声明 SPN。 若要防止此问题,请使用以下方法之一:
- 禁用内核模式身份验证。 (不建议从性能的角度来看)。
- 将 useAppPoolCredentials 设置为 true。 这样做会保留内核模式身份验证的性能优势,同时允许在应用程序池标识下解码 Kerberos 票证。 有关详细信息,请参阅安全身份验证身份验证><。
尽管 Kerberos 身份验证有效,但委派为何失败
在此方案中,请检查以下项:
用于 URL 的 Internet Explorer 区域。 仅允许 Intranet 和受信任的站点区域进行 Kerberos 委派。 (换句话说,仅当确定的区域是 Intranet 或受信任的站点时,Internet Explorer 才会调用 InitializeSecurityContext 时设置
ISC_REQ_DELEGATE
标志。托管站点的 IIS 应用程序池的用户帐户必须具有 在 Active Directory 中设置的委派 标志的受信任帐户。
如果委派仍然失败,请考虑使用适用于 IIS 的 Kerberos Configuration Manager。 此工具允许诊断和修复用于 Kerberos 身份验证的 IIS 配置以及目标帐户上的关联 SPN。 有关详细信息,请参阅 README.md。 可从此处下载工具。
为什么在使用 Kerberos 身份验证时性能不佳
Kerberos 是较旧版本的 Windows Server(如 Windows Server 2008 SP2 和 Windows Server 2008 R2)中基于请求的身份验证协议。 这意味着客户端必须发送 Kerberos 票证(这可以是相当大的 Blob),每个请求都会发送到服务器。 这与依赖于 NTLM 的身份验证方法相反。 默认情况下,NTLM 是基于会话的。 这意味着浏览器在打开与服务器的 TCP 连接时仅对一个请求进行身份验证。 同一 TCP 连接上的每个后续请求不再需要身份验证才能接受请求。 在较新版本的 IIS 中,从 Windows 2012 R2 开始,Kerberos 也是基于会话的。 只有新 TCP 连接上的第一个请求必须由服务器进行身份验证。 后续请求无需包含 Kerberos 票证。
如果在 IIS 7 及更高版本下运行,则可以使用 authPersistNonNTLM 属性更改此行为。 如果该属性设置为 true,则 Kerberos 将变为基于会话。 否则,它将基于请求。 性能会更差,因为每次必须包含要发送到服务器的大量数据。 有关详细信息,请参阅基于请求与基于会话的 Kerberos 身份验证(或 AuthPersistNonNTLM 参数)。
注意
对所有对象盲目使用 Kerberos 身份验证可能不是个好主意。 使用 Kerberos 身份验证通过条件 GET 请求提取数百张图像,这些请求可能会生成 304 个未修改的 响应,就像尝试使用锤子杀死苍蝇一样。 这种方法也不会提供明显的安全收益。
为什么 Kerberos 委派在我的两个林之间失败,尽管它曾经正常工作
假设出现了下面这种情景:
- 应用程序的用户位于林 A 中的域内。
- 应用程序位于林 B 内的域中。
- 林之间有信任关系。
在这种情况下,Kerberos 委派可能会停止工作,即使它以前用于工作,并且你尚未对林或域进行任何更改。 Kerberos 身份验证在此方案中仍然有效。 只有委托失败。
此问题可能是由于 Windows Server 安全更新于 2019 年 3 月和 2019 年 7 月Microsoft发布的。 这些更新禁用了不受约束的 Kerberos 委派(可将 Kerberos 令牌从应用程序委托给后端服务的能力)跨林边界的所有新信任和现有信任。 有关详细信息,请参阅 Windows Server 中传入信任的 TGT 委派更新。
Internet Explorer 功能密钥
这些键是打开或关闭浏览器的某些功能的注册表项。 这些键位于以下注册表位置:
HKEY_USERS\<UserSID>\Software\Microsoft\Internet Explorer\Main\FeatureControl
– 如果在用户级别定义HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\
- 如果在计算机级别定义
应在以下位置之一创建功能密钥,具体取决于是要打开还是关闭该功能:
- 计算机上所有用户
- 仅适用于特定帐户
应在相应的路径下创建这些密钥。 在键内,应声明命名 iexplorer.exe
的 DWORD 值。 每个键的默认值应为 true 或 false,具体取决于功能的所需设置。 默认情况下,这两个功能键FEATURE_INCLUDE_PORT_IN_SPN_KB908209
的值均为 FEATURE_USE_CNAME_FOR_SPN_KB911149
false。 为了完成,下面是注册表的示例导出,方法是将功能键包含在 Kerberos 票证中的端口号设置为 true:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_INCLUDE_PORT_IN_SPN_KB908209]
"iexplore.exe"=dword:00000001