如何编写调用WCF服务的代码并在需要时从Kerberos回退到NTLM?

时间:2010-09-09 00:02:35

标签: wcf sharepoint authentication kerberos ntlm

我需要以编程方式调用WCF服务。该服务可以使用 NTLM或Kerberos身份验证托管,并且需要在其中任何一个下工作。也就是说,如果通过Kerberos连接到服务失败,那么它应该回退到NTLM。

以下是我用于Kerberos身份验证的代码(如果相关,该服务托管在SharePoint 2010中,并且是从Web部件调用的):

public static SiteMembershipSvc.SiteMembershipServiceClient InitialiseSiteMembershipService(string url)
{
    var binding = new BasicHttpBinding();
    binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
    binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
    url = url.EndsWith("/") ? url + SiteMembershipAddress : url + "/" + SiteMembershipAddress;
    var endpoint = new EndpointAddress(url);
    var proxy = new SiteMembershipSvc.SiteMembershipServiceClient(binding, endpoint);
    proxy.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
    return proxy;
}

在NTLM环境中运行时在代理上调用方法会产生错误:

  

HTTP请求未经授权   客户认证方案   '谈判'。身份验证标头   从服务器收到的是'NTLM'。

注意:URL可能位于另一台服务器上的另一个Web应用程序中。我无法检查Web部件的Web应用程序运行的身份验证,并假设它与托管WCF服务的位置相同。

如何(自动或手动)确保身份验证在失败时从Kerberos回退到NTLM?

更新

如上所述,调用Web方法时会发生身份验证错误。但是我不想等待很长时间,因为在几个地方调用了多个Web方法。我想在配置代理的位置测试身份验证(在上面的代码片段中)。

我尝试过使用proxy.Open(),但这似乎不会导致失败。

7 个答案:

答案 0 :(得分:1)

这有点像曲线球,但为什么它会回归到NTLM。我在活动目录和WCF中的安全性都遇到了很大的困难,所有这些都与服务主体名称(SPN)有关。

如果您将服务作为网络服务之外的其他内容运行,则Kerberos将失败,除非您在域中为您的服务声明了SPN。要设置SPN,您需要Windows服务器管理工​​具包,其中包含命令setspn。

setspn -A HTTP\machinename domain\service_account

这将允许Kerberos在域内与您的服务共享客户端凭据。

请做一些阅读,因为根据您的设置,您可以在同一个盒子上运行任何其他服务的kerberos。

答案 1 :(得分:1)

(我认为原帖很老。)

你可以使用BasicHttpBinding以外的东西(比如WsHttpBinding)吗?根据{{​​3}}文章,BasicHttpBinding是绑定对象的一个​​例外,因为它不会自动协商。这就是allowNTLM无效的原因。

答案 2 :(得分:0)

我发布了与here相同的错误消息,并通过创建动态端点解决了这个问题:

public static SiteMembershipSvc.SiteMembershipServiceClient InitialiseSiteMembershipService(string url)
{
    //create endpoint
    EndpointAddress ep = new EndpointAddress(new Uri(string), EndpointIdentity.CreateUpnIdentity("MyDomain\WCFRunAsUser"));
    //create proxy with new endpoint
    SiteMembershipSvc.SiteMembershipServiceClient service = new SiteMembershipSvc.SiteMembershipServiceClient("wsHttp", ep);
    //allow client to impersonate user
    service.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
    //return our shiny new service
    return service;
}

我将WCF服务作为特定的Active Directory用户运行,而不是默认的NETWORK_SERVICE。

答案 3 :(得分:0)

尝试设置:

proxy.ClientCredentials.Windows.AllowNTLM = true;

根据this,AllowNTLM现已过时 - 我不确定正确的选择是什么。

答案 4 :(得分:0)

我猜您使用服务器的完整DNS名称作为服务的地址。尝试使用NETBIOS名称或IP地址。这应该迫使它使用NTLM。

如果您知道服务器使用的协议,您可以将应用配置为使用全名或IP。

希望对你有用。

答案 5 :(得分:0)

答案 6 :(得分:0)

我无法找到自动执行此操作的方法。相反,我已经在必须选择身份验证类型的应用程序中添加了UI。