考虑一个简单的 C# NET Framework 4.0 应用程序,它:
- 使用网络客户端
- 使用 NTLM 进行身份验证(在 IIS 6.0 和 IIS 7.5 服务器上测试)
- 使用 DownloadString() 从 URL 中多次检索字符串
这是一个运行良好的示例:
using System;
using System.Net;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string URL_status = "http://localhost/status";
CredentialCache myCache = new CredentialCache();
myCache.Add(new Uri(URL_status), "NTLM", new NetworkCredential("username", "password", "domain"));
WebClient WebClient = new WebClient();
WebClient.Credentials = myCache;
for (int i = 1; i <= 5; i++)
{
string Result = WebClient.DownloadString(new Uri(URL_status));
Console.WriteLine("Try " + i.ToString() + ": " + Result);
}
Console.Write("Done");
Console.ReadKey();
}
}
}
问题:
启用跟踪时,我发现 NTLM 身份验证不会持续存在。
每次调用 Webclient.DownloadString 时,NTLM 身份验证开始(服务器返回“WWW-Authenticate: NTLM” header ,整个身份验证/授权过程重复;没有“Connection: close” header )。
NTLM 不是应该验证连接,而不是请求吗?
有没有办法让 WebClient 重用现有连接以避免必须重新验证每个请求?
最佳答案
在尝试了 10 天我能想到的所有方法并在此过程中学到了很多东西之后,我终于找到了解决此问题的方法。
诀窍是启用UnsafeAuthenticatedConnectionSharing
通过重写 GetWebRequest
并将 HttpWebRequest
中的属性设置为 true
,您可以返回。
您可能希望将其与 ConnectionGroupName
结合使用属性以避免未经身份验证的应用程序可能使用连接。
这里是修改后的问题示例,可以按预期工作。它打开单个 NTLM 身份验证连接并重用它:
using System;
using System.Net;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string URL_status = "http://localhost/status";
CredentialCache myCache = new CredentialCache();
myCache.Add(new Uri(URL_status), "NTLM", new NetworkCredential("username", "password", "domain"));
MyWebClient webClient = new MyWebClient();
webClient.Credentials = myCache;
for (int i = 1; i <= 5; i++)
{
string result = webClient.DownloadString(new Uri(URL_status));
Console.WriteLine("Try {0}: {1}", i, result);
}
Console.Write("Done");
Console.ReadKey();
}
}
public class MyWebClient : WebClient
{
protected override WebRequest GetWebRequest(Uri address)
{
WebRequest request = base.GetWebRequest(address);
if (request is HttpWebRequest)
{
var myWebRequest = request as HttpWebRequest;
myWebRequest.UnsafeAuthenticatedConnectionSharing = true;
myWebRequest.KeepAlive = true;
}
return request;
}
}
}
此时我还要感谢@Falco Alexander所有的帮助;虽然他的建议对我来说不太奏效,但他确实为我指明了寻找并最终找到答案的正确方向。
关于为每个请求启动 C# WebClient NTLM 身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39787404/