仅在特定机器上调用 Web 服务时出现 401

401 when calling Web Service only on particular machines

我们用 C# 开发了一个 WPF 应用程序,并使用 RestSharp 与一个简单的 Web 服务进行通信,如下所示:

Client = new RestClient(serviceUri.AbsoluteUri);
Client.Authenticator = new NtlmAuthenticator(SvcUserName, SvcPassword.GetString());

一切都很好,直到我们接到电话说在某些机器上(大多数工作)应用程序无法连接到服务。 使用 fiddler 直接调用服务方法有效。然后我们提取了一个小型 .net 控制台应用程序并尝试使用 RestSharp 和直接使用 HttpWebRequest 进行服务调用,但再次失败并显示 401。 现在我们启用了 System.Net 跟踪并注意到了一些东西。在第一个正常的401之后,故障机器产生了这个日志:

System.Net Information: 0 : [4480] Connection#3741682 - Received headers { Connection: Keep-Alive Content-Length: 1293 Content-Type: text/html Date: Mon, 10 Aug 2015 12:37:49 GMT Server: Microsoft-IIS/8.0 WWW-Authenticate: Negotiate,NTLM X-Powered-By: ASP.NET }. System.Net Information: 0 : [4480] ConnectStream#39451090::ConnectStream(Buffered 1293 bytes.) System.Net Information: 0 : [4480] Associating HttpWebRequest#2383799 with ConnectStream#39451090 System.Net Information: 0 : [4480] Associating HttpWebRequest#2383799 with HttpWebResponse#19515494 System.Net Information: 0 : [4480] Enumerating security packages: System.Net Information: 0 : [4480] Negotiate System.Net Information: 0 : [4480] NegoExtender System.Net Information: 0 : [4480] Kerberos System.Net Information: 0 : [4480] NTLM System.Net Information: 0 : [4480] Schannel System.Net Information: 0 : [4480] Microsoft Unified Security Protocol Provider System.Net Information: 0 : [4480] WDigest System.Net Information: 0 : [4480] TSSSP System.Net Information: 0 : [4480] pku2u System.Net Information: 0 : [4480] CREDSSP

System.Net Information: 0 : [4480] AcquireCredentialsHandle(package = NTLM, intent = Outbound, authdata = (string.empty)\corp\svc_account)

System.Net Information: 0 : [4480] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = (null), targetName = HTTP/mysvc.mycorp.com, inFlags = Delegate, MutualAuth, Connection) System.Net Information: 0 : [4480] InitializeSecurityContext(In-Buffers count=1, Out-Buffer length=40, returned code=ContinueNeeded).

工作机器产生这个输出:

System.Net Information: 0 : [3432] Connection#57733168 - Empfangene Statusleiste: Version = 1.1, StatusCode = 401, StatusDescription = Unauthorized. System.Net Information: 0 : [3432] Connection#57733168 - Header { Content-Type: text/html Server: Microsoft-IIS/8.0 WWW-Authenticate: Negotiate,NTLM X-Powered-By: ASP.NET Date: Mon, 10 Aug 2015 15:15:11 GMT Content-Length: 1293 } wurden empfangen. System.Net Information: 0 : [3432] ConnectStream#35016340::ConnectStream(Es wurden 1293 Bytes gepuffert.) System.Net Information: 0 : [3432] Associating HttpWebRequest#64062224 with ConnectStream#35016340 System.Net Information: 0 : [3432] Associating HttpWebRequest#64062224 with HttpWebResponse#64254500 System.Net Information: 0 : [3432] Sicherheitspakete werden enumeriert: System.Net Information: 0 : [3432] Negotiate System.Net Information: 0 : [3432] NegoExtender System.Net Information: 0 : [3432] Kerberos System.Net Information: 0 : [3432] NTLM System.Net Information: 0 : [3432] Schannel System.Net Information: 0 : [3432] Microsoft Unified Security Protocol Provider System.Net Information: 0 : [3432] WDigest System.Net Information: 0 : [3432] TSSSP System.Net Information: 0 : [3432] pku2u System.Net Information: 0 : [3432] CREDSSP

System.Net Information: 0 : [3432] AcquireCredentialsHandle(package = Negotiate, intent = Outbound, authdata = System.Net.SafeSspiAuthDataHandle) System.Net Information: 0 : [3432] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = (null), targetName = HTTP/mysvc.mycorp.com, inFlags = Delegate, MutualAuth, Connection)

System.Net Information: 0 : [3432] InitializeSecurityContext(Anzahl von In-Buffers = 1, Länge von Out-Buffer = 40, zurückgegebener Code = ContinueNeeded).

不知道是不是故障机器上的某些配置会导致这种情况。目前我不确定下一步要看哪里。

更新: 这是我们简单测试工具的代码:

RestClient Client = new RestClient("https://mysvc.mycorp.com/service.svc");
        Client.Authenticator = new NtlmAuthenticator("corp\svc_account", "mypassword");
        var request = new RestRequest("api/Method", Method.POST);
        request.RequestFormat = DataFormat.Json;
        request.AddBody(new { Device_Key = "somestring" });
        request.Timeout = 200000;


        RestResponse response = (RestResponse)Client.Execute(request);

更新 2: 我们现已确认此问题仅发生在新安装的具有更新公司映像的 win 7 计算机上。几乎看起来过去 2 个月的一些更新正在搞砸我们。

这太疯狂了:事实证明,当我在 Windows 7 机器上安装 .net 4.5 时,WebRequest 就成功了!我们认为罪魁祸首是部署到所有客户端计算机的 .NET 4.0 Framework 缺少补丁。 所以,修补你的机器 :)