Могу ли я заставить 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 в том, чтобы взломать его вручную, используя базовую аутентификацию (которая не будет летать для этого прецедента)
Ответы
Ответ 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.