使用 Kerberos 身份验证的 WCF 自承载 Web 服务
WCF self-hosted web service using Kerberos authentication
我正在尝试在自托管 RESTful WCF 服务上启用 Kerberos 身份验证。我可以从 HTTP 流量中看到客户端(即 Internet Explorer)正确地尝试了 Kerberos 身份验证,但由于未知原因,我的自托管服务拒绝了 Kerberos 票证。然后 NTLM 身份验证成功,这是我绝对不希望的。
服务代码:
var binding = new WebHttpBinding();
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.InheritedFromHost;
var host = new WebServiceHost(typeof(TestService), new Uri(@"http://2008Web.ad.mdm.com:3456/testservice"));
ServiceEndpoint ep = host.AddServiceEndpoint(typeof(ITestService), binding, "");
ep.Behaviors.Add(new WebHttpBehavior());
ServiceAuthenticationBehavior sab = null;
sab = host.Description.Behaviors.Find<ServiceAuthenticationBehavior>();
sab.AuthenticationSchemes = System.Net.AuthenticationSchemes.Negotiate;
ServiceMetadataBehavior smb = new ServiceMetadataBeahvior();
smb.HttpGetEnabled = true;
host.Description.Behaviors.Add(smb);
host.Open();
这是观察到的 HTTP 流量:
adfsserver.ad.mdm.com 2008WEB HTTP:Request, GET /testservice/Test
2008WEB adfsserver.ad.mdm.com HTTP:Response, HTTP/1.1, Status: Unauthorized, URL: /testservice/Test , Using Negotiate Authentication
adfsserver.ad.mdm.com 2008WEB HTTP:Request, GET /testservice/Test , Using GSS-API Authorization (****Kerberos Ticket in header*****)
2008WEB adfsserver.ad.mdm.com HTTP:Response, HTTP/1.1, Status: Unauthorized, URL: /testservice/Test , Using GSS-API Authentication
adfsserver.ad.mdm.com 2008WEB HTTP:Request, GET /testservice/Test , Using GSS-API Authorization (****NTLM Ticket in header*****)
2008WEB adfsserver.ad.mdm.com HTTP:Response, HTTP/1.1, Status: Ok, URL: /testservice/Test , Using oRswGaADCgEAoxIEEAEAAABdREAy5JJFLAAAAAA= Authentication
我已尝试将 SPN(服务主体名称)注册为:
setspn -s host/2008Web:3456 2008Web
setspn -s host/2008Web.ad.mdm.com:3456 2008Web
setspn -s http/2008Web:3456 administrator
setspn -s http/2008Web.ad.mdm.com:3456 administrator
setspn -s http/2008Web:3456/testservice administrator
setspn -s http/2008Web.ad.mdm.com:3456/testservice administrator
Windows 事件日志和 WCF 日志记录均未提供有关 Kerberos 身份验证失败原因的任何指示。
当我在 IIS 中托管相同的服务时,Kerberos 身份验证工作正常。此外,在 IIS 中托管服务时,我从来不需要注册(或识别)SPN,它可以正常工作。直到我开始搜索这个问题时,人们才开始谈论 SPN。我以前从来不用担心 SPN,而且我过去使用过几个 IIS 托管的启用 Kerberos 的 Web 服务。
秘诀是什么?我错过了什么?如果有人能指出正确的方向,我将不胜感激。是否有任何其他日志我可以 examine/enable 来希望确定 HTTP 堆栈为什么决定将 Kerberos 请求放在地板上?一定有某种方法可以确定失败的原因。
我很确定这个问题与服务器主体名称无关,因为我可以看到域控制器确实授予了 Kerberos 票证。在域控制器上,我没有看到 KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN 而是 TGS-REP(授予 Kerberos 票证)。此外,我在服务器的 HTTP 请求中看到了 Kerberos 票证。因此,问题一定出在 WCF 自承载服务上。
使用启用了 Kerberos 的 iOS7 应用程序,我发现网络跟踪略有不同。我看到域控制器将 Kerberos 票证授予 iOS7 应用程序,然后我看到 Kerberos 票证呈现给 WCF 服务(在 HTTP 级别)。但是,WCF 服务(在 HTTP 级别)的响应是 HTTP 400,错误请求。根据我的阅读,HTTP 400 通常与客户端的问题有关。也就是说,它以 HTTP 服务器端不支持的格式呈现 HTTP 数据包。尽管如此,就像上面的 IE 示例一样,当 WCF 服务托管在 IIS 中时,一切正常。 WCF 日志记录中的信息为零(它永远不会达到该级别,因为它被 HTTP 堆栈拒绝)并且事件日志中与此事件关联的信息为零。
我在上述 WCF 服务配置中是否遗漏了什么?你在上面看到的就是所有的东西。也就是说,我没有使用应用程序配置文件来配置此 WCF 服务。正在以编程方式配置 WCF 服务。如果我删除身份验证配置,那么一切正常。 iOS7 应用程序、Safari 和 IE 都可以与我的自托管 WCF 服务成功交互。
在没有借助常用调试工具(http 错误日志、事件查看器、WCF 日志记录等)的帮助后,我发现了问题所在。如上所述,我可以看到 kerberos 票证到达服务器(wire stark),但随后请求被拒绝。我推测可能是http header超过了最大长度。我找到了以下文章:
Kerberos authentication failing with 401
调整以下 http 注册表设置后,kerberos 身份验证开始工作:
MaxRequestBytes - set to 1048576
MaxFieldLength - set to 65534
虽然以下文章没有直接帮助我解决我的问题,但也许有人会从中发现一些价值:
Things to check when Kerberos authentication fails using IIS/IE
我正在尝试在自托管 RESTful WCF 服务上启用 Kerberos 身份验证。我可以从 HTTP 流量中看到客户端(即 Internet Explorer)正确地尝试了 Kerberos 身份验证,但由于未知原因,我的自托管服务拒绝了 Kerberos 票证。然后 NTLM 身份验证成功,这是我绝对不希望的。
服务代码:
var binding = new WebHttpBinding();
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.InheritedFromHost;
var host = new WebServiceHost(typeof(TestService), new Uri(@"http://2008Web.ad.mdm.com:3456/testservice"));
ServiceEndpoint ep = host.AddServiceEndpoint(typeof(ITestService), binding, "");
ep.Behaviors.Add(new WebHttpBehavior());
ServiceAuthenticationBehavior sab = null;
sab = host.Description.Behaviors.Find<ServiceAuthenticationBehavior>();
sab.AuthenticationSchemes = System.Net.AuthenticationSchemes.Negotiate;
ServiceMetadataBehavior smb = new ServiceMetadataBeahvior();
smb.HttpGetEnabled = true;
host.Description.Behaviors.Add(smb);
host.Open();
这是观察到的 HTTP 流量:
adfsserver.ad.mdm.com 2008WEB HTTP:Request, GET /testservice/Test
2008WEB adfsserver.ad.mdm.com HTTP:Response, HTTP/1.1, Status: Unauthorized, URL: /testservice/Test , Using Negotiate Authentication
adfsserver.ad.mdm.com 2008WEB HTTP:Request, GET /testservice/Test , Using GSS-API Authorization (****Kerberos Ticket in header*****)
2008WEB adfsserver.ad.mdm.com HTTP:Response, HTTP/1.1, Status: Unauthorized, URL: /testservice/Test , Using GSS-API Authentication
adfsserver.ad.mdm.com 2008WEB HTTP:Request, GET /testservice/Test , Using GSS-API Authorization (****NTLM Ticket in header*****)
2008WEB adfsserver.ad.mdm.com HTTP:Response, HTTP/1.1, Status: Ok, URL: /testservice/Test , Using oRswGaADCgEAoxIEEAEAAABdREAy5JJFLAAAAAA= Authentication
我已尝试将 SPN(服务主体名称)注册为:
setspn -s host/2008Web:3456 2008Web
setspn -s host/2008Web.ad.mdm.com:3456 2008Web
setspn -s http/2008Web:3456 administrator
setspn -s http/2008Web.ad.mdm.com:3456 administrator
setspn -s http/2008Web:3456/testservice administrator
setspn -s http/2008Web.ad.mdm.com:3456/testservice administrator
Windows 事件日志和 WCF 日志记录均未提供有关 Kerberos 身份验证失败原因的任何指示。
当我在 IIS 中托管相同的服务时,Kerberos 身份验证工作正常。此外,在 IIS 中托管服务时,我从来不需要注册(或识别)SPN,它可以正常工作。直到我开始搜索这个问题时,人们才开始谈论 SPN。我以前从来不用担心 SPN,而且我过去使用过几个 IIS 托管的启用 Kerberos 的 Web 服务。
秘诀是什么?我错过了什么?如果有人能指出正确的方向,我将不胜感激。是否有任何其他日志我可以 examine/enable 来希望确定 HTTP 堆栈为什么决定将 Kerberos 请求放在地板上?一定有某种方法可以确定失败的原因。
我很确定这个问题与服务器主体名称无关,因为我可以看到域控制器确实授予了 Kerberos 票证。在域控制器上,我没有看到 KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN 而是 TGS-REP(授予 Kerberos 票证)。此外,我在服务器的 HTTP 请求中看到了 Kerberos 票证。因此,问题一定出在 WCF 自承载服务上。
使用启用了 Kerberos 的 iOS7 应用程序,我发现网络跟踪略有不同。我看到域控制器将 Kerberos 票证授予 iOS7 应用程序,然后我看到 Kerberos 票证呈现给 WCF 服务(在 HTTP 级别)。但是,WCF 服务(在 HTTP 级别)的响应是 HTTP 400,错误请求。根据我的阅读,HTTP 400 通常与客户端的问题有关。也就是说,它以 HTTP 服务器端不支持的格式呈现 HTTP 数据包。尽管如此,就像上面的 IE 示例一样,当 WCF 服务托管在 IIS 中时,一切正常。 WCF 日志记录中的信息为零(它永远不会达到该级别,因为它被 HTTP 堆栈拒绝)并且事件日志中与此事件关联的信息为零。
我在上述 WCF 服务配置中是否遗漏了什么?你在上面看到的就是所有的东西。也就是说,我没有使用应用程序配置文件来配置此 WCF 服务。正在以编程方式配置 WCF 服务。如果我删除身份验证配置,那么一切正常。 iOS7 应用程序、Safari 和 IE 都可以与我的自托管 WCF 服务成功交互。
在没有借助常用调试工具(http 错误日志、事件查看器、WCF 日志记录等)的帮助后,我发现了问题所在。如上所述,我可以看到 kerberos 票证到达服务器(wire stark),但随后请求被拒绝。我推测可能是http header超过了最大长度。我找到了以下文章:
Kerberos authentication failing with 401
调整以下 http 注册表设置后,kerberos 身份验证开始工作:
MaxRequestBytes - set to 1048576
MaxFieldLength - set to 65534
虽然以下文章没有直接帮助我解决我的问题,但也许有人会从中发现一些价值:
Things to check when Kerberos authentication fails using IIS/IE