HTTP 407 (требуется проверка подлинности прокси)
У меня есть несколько основных вопросов по аутентификации HTTP
1) Как клиент узнает о типе аутентификации Сервера (Basic/Digest/NTLM) HTTP?
это настраивается на стороне HTTP-сервера?
Мой ответ: для сервера будет задан тип аутентификации, который он должен выполнять с клиентом. Таким образом, наш клиентский API(в C# HttpWebRequest API) автоматически позаботится об этом. Лучшее использование Wireshrk с применением фильтра HTTP; Вы получите IP-адрес источника и назначения на уровне Интернет-протокола. И порт src и dest на протоколе управления передачей и тип аутентификации на уровне http.
2) Если я размещу прокси-сервер squid linux между клиентом и сервером; есть ли необходимость в моем клиентском коде также знать о типе аутентификации прокси-сервера? или тип аутентификации относится только к конечному HTTP-серверу?
Мой ответ: если прокси-сервер squid находится между клиентом и сервером; он не будет использовать HTTP-аутентификацию. Он может использовать: а) DB: использует базу данных SQL; б) LDAP: использует протокол облегченного доступа к каталогам. c) RADIUS: использует сервер RADIUS для проверки логина. и т. д. Поэтому мы должны упомянуть учетные данные для аутентификации прокси в заголовках HTTP.
3) Использование WireShark обнаружил, что существует три запроса от браузера к серверу для выполнения одного запроса.
а) Браузер отправляет запрос без каких-либо учетных данных аутентификации; Таким образом, сервер ответил 401 вместе с реламом и одноразовым номером.
WWW-Authenticate: Digest realm="realm", qop="auth", nonce="MTM1OTYyMzkyNDU4MzpiOWM0OWY0NmMzMzZlMThkMDJhMzRhYmU5NjgwNjkxYQ=="\r\n <BR>
б) во второй раз браузер отправляет запрос с учетными данными, relay, nonce, cnonce; но все равно сервер ответил 401;
WWW-Authenticate: Digest realm="realm", qop="auth", nonce="MTM1OTYyMzk0OTAyMTo3Njk3MDNhZTllZDQyYzQ5MGUxYzI5MWY2MGU5ZDg0Yw==", stale="true"\r\n
c) браузер в третий раз отправляет тот же запрос с теми же учетными данными, relm, nonce, cnonce. На этот раз сервер отправляет 200 ок.
Мой вопрос во второй и третий раз Браузер отправить тот же запрос; почему сервер не удалось во второй раз и успех в третий раз. Это из-за реализации моего сервера? (У меня REST Java-сервер с фильтром SPRING Security).
У меня есть клиент C# HTTP;
где в первый раз HttpWebRequest отправляется без учетных данных, хотя установлен System.Net.NetworkCredentials; так что в клинете 407 с релом и одноразовым номером.
Второй раз HttpWebRequest является scuccess. Нет третьего запроса от этого клиента, как браузер.
Почему такая разница между браузером и клиентом C#?
Мой ответ: я до сих пор не знаю, что здесь происходит: Q3.
4) Теперь реальная проблема, с которой я сталкиваюсь, это когда SQUID LINUX PROXY оказался между нашим Клиентом и HTTP-сервером, Браузер выполнил ту же аутентификацию с тремя запросами и успешно. Однако C# HttpWebRequest не удалось (401) во втором запросе и достиг блока кеша (исключение){} и не пытался в третий раз.
Не могли бы вы, пожалуйста, кто-нибудь объяснить мне, как решить эту проблему в клиенте C#, когда PROXY SERVER находится между ними?
Ниже код выполняет запрос GET.
HttpWebRequest request = WebRequest.Create("url") as HttpWebRequest;
request.Credentials = new NetworkCredential(loginUserName, password);
WebResponse response = request.GetResponse();
Обратите внимание, что наш запрос к прокси отправляется по протоколу TCP, а не по протоколу HTTP. Затем от PROXY до SERVER обменивается данными по протоколу HTTP. Но HTTP-запрос от Прокси содержит информацию о ip нашего клиента в заголовке HTTP. X-Forwarded-For
,
Ниже приведены возможные решения
Эти решения требуются только в том случае, если ваш прокси-сервер требует какой-либо аутентификации, иначе проигнорируйте ее.
Решение 1: работа для меня
request.Proxy.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
Решение 2:
IWebProxy proxy = WebRequest.GetSystemWebProxy();
proxy.Credentials = new NetworkCredential(UserName, UserPassword, UserDomain);
request.Proxy = proxy;
Решение 3, данное Мартином:
var proxy = new WebProxy ("http://localhost:3128/");
proxy.Credentials = new NetworkCredential (UserName, UserPassword, UserDomain);
request.Proxy = proxy;
Узнайте больше об аутентификации прокси на http://wiki.squid-cache.org/Features/Authentication
1 ответ
Это протокол вызова / ответа. Обычно клиент делает первоначальный запрос без каких-либо заголовков аутентификации (вы можете установить request.PreAuthenticate = true
отправить учетные данные с первым запросом).
Затем сервер отвечает списком методов аутентификации, которые он поддерживает.
Если пользователь не указал явно метод аутентификации, используя CredentialsCache
среда выполнения попробует их все, от сильнейшего до слабого. Некоторые протоколы (например, NTLM) требуют многократных запросов от клиента к серверу. Теоретически, дайджест должен работать с одним, без понятия, почему он отправляет запрос дважды.
Что касается вашего прокси-вопроса, есть два разных типа аутентификации:
- Аутентификация целевого веб-сервера, прокси просто проходит это, и вам не нужен специальный код в вашем клиенте.
- В дополнение к этому, самому прокси-серверу также может потребоваться аутентификация, которая может отличаться от аутентификации целевого веб-сервера.
Вы указываете это с помощью
var proxy = new WebProxy ("http://localhost:3128/");
proxy.Credentials = new NetworkCredential ("username", "password");
а потом
WebRequest.DefaultWebProxy = proxy;
или же
request.Proxy = proxy;
Не устанавливайте учетные данные на WebProxy
если ваш прокси-сервер не использует аутентификацию.
Если вы не можете заставить аутентификацию работать при использовании прокси-сервера, посмотрите на реальные запросы, которые отправляются между тремя сторонами (веб-сервер, прокси, клиент) с помощью Wireshark.