Проверка подлинности NTLM WebClient c# начинается для каждого запроса
рассмотрим простое приложение c# NET Framework 4.0, которое:
- использует WebClient
- аутентифицируется с помощью NTLM (проверено на IIS 6.0 и IIS 7.5 server)
- извлекает строку из URL несколько раз с помощью DownloadString ()
вот пример, который прекрасно работает:
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.Вызывается строка загрузки, запускается аутентификация NTLM (сервер возвращает заголовок "WWW-Authenticate: NTLM" и весь процесс аутентификации/авторизации повторяется; нет заголовка "Connection: close").
разве NTLM не должен был аутентифицировать соединение, а не запрос?
есть ли способ сделать WebClient повторно использовать существующее соединение, чтобы избежать повторной аутентификации каждого запроса?
2 ответов
после 10 дней пробовать все, что я мог думать и учиться много в этом процессе, я наконец-то решил исправить эту проблему.
фокус в том, чтобы включить UnsafeAuthenticatedConnectionSharing переопределив 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 " + i.ToString() + ": " + Result);
}
Console.Write("Done");
Console.ReadKey();
}
}
public class MyWebClient : WebClient
{
protected override WebRequest GetWebRequest(Uri address)
{
WebRequest request = (WebRequest)base.GetWebRequest(address);
if (request is HttpWebRequest)
{
var myWebRequest = request as HttpWebRequest;
myWebRequest.UnsafeAuthenticatedConnectionSharing = true;
myWebRequest.KeepAlive = true;
}
return request;
}
}
}
в этот момент я также хотел бы поблагодарить @Falco Alexander за всю помощь; хотя его предложения не совсем сработали для меня, он указал мне в правильном направлении, чтобы искать и, наконец, найти ответ.
проверьте настройки IIS, например, хотя это должно быть по умолчанию.
<windowsAuthentication
enabled="True"
authPersistSingleRequest="False"
UseKernelMode>
</windowsAuthentication>
Ref:https://msdn.microsoft.com/en-us/library/aa347472.aspx
вы проверили зону вашего localhost IIS в? Это была ошибка со стороны клиента в прошлом при работе с wininet. Проверьте поведение WebClient по умолчанию.
Edit:
после воспроизведения ошибки я мог бы выяснить, что это недостающий NTLM предварительная проверка реализация WebClient, который держит вас от одного запроса 401:
var WebClient = new PreAuthWebClient();
WebClient.Credentials = new NetworkCredential("user", "pass","domain");
//Do your GETs
Public class PreAuthWebClient: WebClient
{
protected override WebRequest GetWebRequest (Uri address)
{
WebRequest request = (WebRequest) base.GetWebRequest (address);
request.PreAuthenticate = true;
return request;
}
}