Ответ 1
Это поведение по умолчанию классов HttpClient
и HttpWebRequest
, которое отображается следующим образом.
Примечание. Ниже текст объясняет субоптимальное поведение, вызывающее проблему, описанную в вопросе. Скорее всего, вы не должны писать свой код, как это. Вместо этого прокрутите ниже скорректированный код
В обоих случаях создайте экземпляр объекта NetworkCredenatial
и укажите там имя пользователя и пароль.
var credentials = new NetworkCredential( username, password );
Если вы используете HttpWebRequest
- установить .Credentials
свойство:
webRequest.Credentials = credentials;
Если вы используете HttpClient
- передайте объект учетных данных в HttpClientHandler
(измененный код из здесь):
var client = new HttpClient(new HttpClientHandler() { Credentials = credentials })
Затем запустите Fiddler и запустите запрос. Вы увидите следующее:
- запрос отправляется без заголовка авторизации
- служба отвечает HTTP 401 и WWW-аутентификацией: Basic realm = "UrRealmHere"
- запрос отправляется с соответствующим заголовком авторизации (и успешно)
Это объясняется здесь - клиент не знает заранее, что услуге требуется Basic и пытается согласовать протокол аутентификации (а если услуге требуется дайджест отправка основных заголовков в открытом виде бесполезна и может поставить под угрозу клиента).
Примечание: здесь субоптимальное объяснение поведения заканчивается, и объясняется лучший подход. Скорее всего, вы должны использовать код снизу вместо кода сверху.
В тех случаях, когда известно, что услуге требуется Basic, дополнительный запрос может быть устранен следующим образом:
Не устанавливайте .Credentials
, вместо этого добавляйте заголовки вручную, используя код здесь. Кодируйте имя пользователя и пароль:
var encoded = Convert.ToBase64String( Encoding.ASCII.GetBytes(
String.Format( "{0}:{1}", username, password ) ) );
При использовании HttpWebRequest
добавьте его в заголовки:
request.Headers.Add( "Authorization", "Basic " + encoded );
и при использовании HttpClient
добавьте его в заголовки по умолчанию:
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue( "Basic", encoded );
Когда вы делаете это, запрос отправляется с правом заголовком авторизации каждый раз. Обратите внимание, что вы не должны устанавливать .Credentials
, иначе, если имя пользователя или пароль неверны, один и тот же запрос будет отправляться дважды в оба раза с неправильными учетными данными и оба раза, конечно, уступая HTTP 401.