Подтвердить что ты не робот

Могу ли я заставить HttpWebRequest включать учетные данные Windows, не дожидаясь вызова 401?

Мое приложение взаимодействует с внутренним веб-интерфейсом, который требует аутентификации.

Когда я отправляю запрос, я получаю запрос 401, как и ожидалось, происходит рукопожатие, повторно отправленный аутентифицированный запрос и все прекращается.

Однако я знаю, что требуется auth. Почему я должен ждать вызова? Могу ли я заставить запрос отправлять учетные данные в запросе первый?

Моя генерация запросов выглядит так:

   private static HttpWebRequest BuildRequest(string url, string methodType)
   {
       var request = HttpWebRequest.CreateHttp(url);
       request.PreAuthenticate = true;
       request.AuthenticationLevel = AuthenticationLevel.MutualAuthRequested;
       request.Credentials = CredentialCache.DefaultNetworkCredentials;
       request.Proxy.Credentials = CredentialCache.DefaultNetworkCredentials;
       request.ContentType = CONTENT_TYPE;
       request.Method = methodType;
       request.UserAgent = BuildUserAgent();
       return request;
   }

Даже с этим кодом заголовок auth не входит в первоначальный запрос.

Я знаю, как включить информацию об аутентификации с базовым.... что я хочу сделать, это использовать Windows Auth для пользователя, выполняющего приложение (поэтому я не могу сохранить пароль в файле конфигурации).

UPDATE Я также попытался использовать HttpClient и собственное свойство .Credentials с тем же результатом: в начальный запрос не добавлен заголовок auth.

Единственный способ получить заголовок auth в том, чтобы взломать его вручную, используя базовую аутентификацию (которая не будет летать для этого прецедента)

4b9b3361

Ответ 1

Ntlm - это протокол аутентификации на основе протокола/ответа. Вам нужно сделать первый запрос, чтобы сервер мог выполнить вызов, а затем в последующем запросе клиент отправил ответ на вызов. Затем сервер проверяет этот ответ с контроллером домена, предоставляя ему вызов и ответ, который отправил клиент. Не зная проблемы, вы не можете отправить ответ, поэтому требуется 2 запроса.

Базовая аутентификация основана на пароле, поэтому вы можете коротко закоротить это, отправив учетные данные с первым запросом, но по моему опыту это может быть проблемой для некоторых серверов.

Более подробная информация доступна здесь: http://msdn.microsoft.com/en-us/library/windows/desktop/aa378749(v=vs.85).aspx

Ответ 2

Я не уверен на 100%, но я подозреваю, что нет никакого способа обойти это; это просто способ HttpWebRequest.

В онлайн-источнике .NET функция DoSubmitRequestProcessing, которая здесь, вы можете увидеть этот комментарий сразу после начала функции, строка 1731:

        // We have a response of some sort, see if we need to resubmit
        // it do to authentication, redirection or something
        // else, then handle clearing out state and draining out old response.

Немного дальше (строка 1795) (некоторые строки удалены для краткости)

if (resubmit)
{   
   if (CacheProtocol != null && _HttpResponse != null) CacheProtocol.Reset();
   ClearRequestForResubmit(ntlmFollowupRequest);
   ...
}

И в строке ClearRequestForResubmit 5891:

// We're uploading and need to resubmit for Authentication or Redirect.

а затем (строка 5923):

// The second NTLM request is required to use the same connection, don't close it
     if (ntlmFollowupRequest) {....}

В мои (по общему признанию, n00bish) глаза эти комментарии, похоже, указывают на то, что разработчики решили следовать "стандартному" протоколу "запрос-ответ" для NTML/Kerberos и не включать какой-либо способ отправки заголовков аутентификации вверх.

Ответ 3

Настройка PreAuthenticate - это то, что вы хотите, что вы делаете. Самый первый запрос по-прежнему будет выполнять рукопожатие, но для последующих запросов он автоматически отправит учетные данные (на основе используемого URL-адреса). Вы можете прочитать здесь: http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.preauthenticate(v = vs 0,110).aspx.