如何在 Windows Server 2012 r2 上调试 NTLM 身份验证

How to debug NTLM authentication on Windows Server 2012 r2

我已经在虚拟机 运行 Windows Server 2012 r2 上设置了 SOAP 服务。 我使用 NTLM 保护它,并设法使用 SoapUI 从主机访问它。到目前为止一切顺利...

我现在正在尝试访问我的服务,仍然是从主机,但这次使用的是 golang 程序。我正在使用 this library 来完成它(我只需要实现 GenerateNegotiateMessage() 方法并确保协商标志与 SoapUI 的标志相同)。

为了确保我做的正确,我下载了 SoapUI 的源代码并比较了我的 golang 程序和 SoapUI 的输出(NegotiateMessage 和 AuthenticateMessage)。如果我修复输入(时间戳和随机客户端质询),我会得到相同的输出。但是,当我尝试连接到该服务时,我得到一个带有 "Access is denied due to invalid credentials" 的 401。无需说我 100% 确定凭据是正确的,因为我能够使用 SoapUI 使用相同的凭据访问该服务。所以我的go代码肯定有问题。但要弄清楚,我需要来自 Windows 服务器的更多日志。知道我可以从哪里开始寻找吗?

下面是我的 Soap 服务的web.config:

<?xml version="1.0"?>
<configuration>
  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.5"/>
    <httpRuntime targetFramework="4.5"/>
    <trace enabled="true" pageOutput="true" requestLimit="40" localOnly="false"/>
  </system.web>
  <system.serviceModel>

    <diagnostics wmiProviderEnabled="true">
      <messageLogging
           logEntireMessage="true"
           logMalformedMessages="true"
           logMessagesAtServiceLevel="true"
           logMessagesAtTransportLevel="true"
           maxMessagesToLog="3000"
       />
    </diagnostics>

    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="false"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>

    <bindings>
      <basicHttpBinding>
        <binding>
          <security mode="TransportCredentialOnly">
            <transport clientCredentialType="Ntlm" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>

    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <directoryBrowse enabled="true"/>
  </system.webServer>
  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel" switchValue="All" propagateActivity="true">
        <listeners>
          <add name="myListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="C:\logs\TextWriterOutput.log"/>
        </listeners>
      </source>
    </sources>
  </system.diagnostics>
</configuration>

非常感谢您的帮助!

我最终设法解决了我的问题。 这是因为我没有在我的 golang 程序中完全读取我的 HTTP 请求的响应主体。因此,每次我发出请求时,服务器都将其解释为一个新连接,但 NTLM 身份验证方案要求所有请求都在一个连接中发出。实际上是这个 answer 解决了我的问题。

对于未来的编码人员,如果您想重用相同的连接,您应该使用以下代码:

res, _ := client.Do(req)
io.Copy(ioutil.Discard, res.Body)
res.Body.Close()

总而言之,我没能从 Windows 的日志中获得太多信息。使我走上正轨的工具是您可以从 IIS 管理器访问的失败请求跟踪器和用于比较我的程序和 SoapUI 的程序发出的请求的旧 Wireshark。

希望这对某人有用。