为啥 kerberos 在 WCF 中默认为 NTLM?

Posted

技术标签:

【中文标题】为啥 kerberos 在 WCF 中默认为 NTLM?【英文标题】:Why is kerberos defaulting to NTLM in WCF?为什么 kerberos 在 WCF 中默认为 NTLM? 【发布时间】:2011-01-20 02:41:53 【问题描述】:

有一个简单的 WCF 演示应用程序,它有两个控制台项目——主机和客户端。两者都在我的机器上运行(win 7 box)。我正在使用 netTcpBinding,它使用 Windows 身份验证。

问题是身份验证从 kerberos 降级到 NTLM,我不知道为什么。

如果我使用

<clientCredentials>
   <windows allowNtlm="true" />
</clientCredentials>

在客户端,一切都很酷。但是,如果我将其更改为 false,则会出现以下异常:

SecurityNegotiationException: 远程服务器不满足 相互身份验证要求。

这表明 kerberos 失败,并且由于客户端不允许 NTLM,因此调用会导致引发异常。

这是项目的问题,还是我的开发机器配置造成的外部问题?


解决方案:

显然,我必须在客户端配置中指定服务器的身份。就我而言,服务器以我的身份运行,因此我修改了客户端:

<client>
  <endpoint address="net.tcp://dev7.HurrDurr.com:12345/MyService" 
            binding="netTcpBinding" 
            bindingConfiguration="MyBindingConfigurationLol" 
            behaviorConfiguration="HurrDurrServiceEndpoint" 
            contract="ShaolinCore.ICommunicationService">
    <!-- start changes here -->
    <identity>
      <userPrincipalName value="myusername@mydomain"/>
    </identity>
    <!-- end changes here -->
  </endpoint>
</client>

我不确定为什么这可以解决问题。好的,现在在客户端我完全信任服务器(嘿,我认识那个人!)。但是既然 NTLM 不如 kerberos 安全,为什么不反过来呢?如果我不完全信任服务器,我使用 kerberos,否则 ntlm 很好。

或者,OTOH,如果我不完全信任服务器,为什么它完全可以工作? “SecurityException:未设置端点身份。WCF 无法信任服务器的身份,不会传输客户端身份。”

【问题讨论】:

这似乎是 serverfault.com 的问题。 重新列出的解决方案:正是由于这个原因,Kerberos 更加安全——服务器是一个受信任且已知的来源,在地址 进程运行时都具有保证的身份那个地址。以其他用户身份运行的服务帐户将无法处理您的请求。 @hogan 我认为 kerb/ntlm 更多的是关于身份验证而不是授权。让我使用 kerb 向任何服务器进行身份验证;一旦我知道服务是谁,我就可以决定是否要与他们打交道。如果我使用遏制进行身份验证,则我拥有受信任的第三方 (AD) 提供的服务的身份。如果服务被欺骗,我可以通过该身份来判断,如果不是预期的,则抛出异常。在 WCF 中,欺骗服务器似乎会失败,然后通过 ntlm。这对我来说似乎并不安全。与任何人进行身份验证,如果他们不是我所期望的,就扔掉。 听起来不错,但这不是它的实现方式。 【参考方案1】:

当我在 IIS4、5 和 6 开发团队工作时,我们经常遇到这种情况!要使 Curb 工作,您需要满足以下条件:

1) 双方都支持 curb(目前所有支持的 Windows 版本都支持 Curb)

2) 机器对 Active Directory 的身份验证

3) 为服务器端点注册的服务主体名称 (SPN)。在“过去的美好时光”中,您必须使用 SetSPN.exe 手动执行此操作。 SPN 只是 Curb 将连接到的端点;它需要这些数据来支持相互授权。大多数应用都会为您调用 appprop API 来完成这项工作 (DsWriteAccountSpn)

如果上述任何步骤不正确,Windows通常默认为 NTLM,它只为您提供客户端身份验证。

希望对您有所帮助! - 迈克尔

【讨论】:

我读过一两本关于 Windows 安全的书,但有时它仍然令人困惑。我也不明白 WCF 如何处理相互身份验证,所以它变得更加困难。为什么我必须提供服务器 UPN/SPN/DNS 才能在客户端启用遏制?如果我不完全信任服务器,为什么 ntlm 比 kerb 更好?还是客户端需要向第三方提供服务身份?为什么服务不能直接提供?为什么我的头疼? Kerb 需要对客户端和服务器进行身份验证,我指的是 计算机。当您的客户端代码 (WCF) 发出连接到服务的请求时,它需要确切地知道它正在连接到什么,因此管理员需要将服务器应用程序的 SPN 添加到 AD - 本质上是您'对 Curb 说“我需要连接到这个 SPN”。在许多情况下,等式的服务器端注册一个 SPN,但前提是它有能力这样做。 NTLM 并不比 Kerb 好,NTLM 只对客户端进行身份验证,所以服务器知道你是谁,但你不知道你在连接谁。 另外:kerberos 只能在通过 DNS 名称调用服务时使用。通过 IP 地址调用服务将导致使用 NTLM【参考方案2】:

通过 MSDN 仅供参考: netTcpBinding:默认绑定使用带有协商身份验证的传输安全性。 此协商尝试使用 Kerberos,但如果这不起作用,它将回退并使用旧的 NTLM 协议。如果您在域环境中,Kerberos 是一个不错的选择;为了使用它,您需要您的服务和客户端都在域帐户下运行。您还需要为您的服务配置服务主体名称 (SPN)。

【讨论】:

所以理论上在阅读了我最初没有阅读的 cmets 之后,这种行为似乎是设计使然。【参考方案3】:

也许 MSDN 上的这个页面 - Debugging Windows Authentication Errors - 可以帮助您弄清楚发生了什么 - 关于何时使用 NTLM 与 Kerberos 似乎相当棘手。

【讨论】:

k... 两端的域用户,检查。完全限定的 URL,已更新,没有区别。添加了身份/UPN ...没有区别。在客户端上配置 SPN 身份...BINGO! @Will:酷,我正要建议你检查服务器和客户端上的 SPN。【参考方案4】:

服务器是如何配置的?配置文件中有&lt;authentication mode="Windows"/&gt;&lt;identity impersonate="true"/&gt; 吗?

您通过配置文件中的 authentication 标签设置认证模式:

<configuration>
  <system.web>
    <authentication mode="Windows" />
  </system.web>
</configuration>

【讨论】:

我认为这些仅适用于 http 绑定。但是,我指定我的 clientCredentialType 是 Windows。 同样,如果客户端允许使用 ntlm,它会工作,否则会失败(我相信,kerberos 不可用)。 AFAIK 它们不仅适用于 http。 我没有看到任何与 tcp 相关的 authenticationMode。然而,我也没有看到身份,这最终是解决方案。确切地说,在 tcp 绑定中,您在哪里设置身份验证模式(在 xml 中,而不是在代码 kthx 中)? 这是一个控制台应用程序;我不认为我登录网站的方式与我的经历有多大关系...

以上是关于为啥 kerberos 在 WCF 中默认为 NTLM?的主要内容,如果未能解决你的问题,请参考以下文章

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

无法通过 Safari 使用 Kerberos 约束委派通过 Web 应用程序访问后端 WCF 服务

kerberos 身份验证-功能组

为啥 MIT-Kerberos 的“本地领域推荐”失败?

为啥 wcf 中 System.Web.HttpContext.Current.Session 总是为Null

为啥我们在启用 Kerberos 的 EMR 集群上使用直线连接到 Hive 时使用 Hive 服务主体?