Invoke-Webrequest получает 401 на POST, но не на GET с базовой аутентификацией

У меня есть сайт разработчика с включенной базовой аутентификацией. Я получаю, чтобы получить страницу, используя следующее, чтобы добавить базовую аутентификацию в заголовки:

$creds = "$($BASIC_AUTH_USER):$($BASIC_AUTH_PASS)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($creds))
$basicAuthValue = "Basic $encodedCreds"
$headers = @{
    Authorization = $basicAuthValue
}

$login = Invoke-WebRequest $url -SessionVariable session -UseBasicParsing -Headers $headers

Но я не могу опубликовать на тот же URL:

$fields = @{ Email = $SITE_USER; Password = $SITE_PASS; }
$login = Invoke-WebRequest -Uri $url -Method POST -WebSession $session -Body $fields -UseBasicParsing -Headers $headers

Я получаю 401 Несанкционированный обратно. Все работает нормально, если я отключаю базовую аутентификацию на сайте. Так что я знаю, что это не проблема с сервером. Я могу POST, используя мой браузер.

Изменить: Таким образом, кажется, базовая аутентификация работает правильно, когда я отлаживаю на сервере. Но мой сервер возвращает перенаправление, которое затем заставляет Invoke-Webrequest интерпретировать это как 401.

Любая идея о том, почему это не может работать?

2 ответа

Вы получаете это поведение из-за перенаправления; при выполнении этого дополнительного запроса к месту перенаправления заголовок авторизации не включается.

По этой причине PowerShell 6.0.0 добавил параметр PreserveAuthorizationOnRedirect.

Указывает, что командлет должен сохранять заголовок авторизации, если он присутствует, при перенаправлениях.
По умолчанию командлет удаляет заголовок авторизации перед перенаправлением. Указание этого параметра отключает эту логику для случаев, когда заголовок необходимо отправить в место перенаправления.

Ссылка Invoke-WebRequest


В качестве альтернативы, если вы не используете PowerShell 6, вы можете обойти его с помощью сценария более низкого уровня, используя System.Net.WebRequest который определяет свойство AllowAutoRedirect это может быть установлено в False для того, чтобы пропустить перенаправление после успешного POST, избегая ошибки 401.

Обратите внимание, что вы должны позаботиться о таких вещах, как форматирование данных / тела (json, form-urlencoded, ...) и http-заголовки самостоятельно.

Сценарий будет выглядеть здесь ниже.
Обратите внимание на строку с AllowAutoRedirect = $false,

$creds = "$($BASIC_AUTH_USER):$($BASIC_AUTH_PASS)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($creds))
$basicAuthValue = "Basic $encodedCreds"

$url = "http://your.url"
$request = [System.Net.WebRequest]::CreateHttp($url);   
$request.Method = "post"
$request.Headers.Add("Authorization", $basicAuthValue)
$request.AllowAutoRedirect = $false

$body = "your formatted data goes here"
$bytes = [System.Text.Encoding]::UTF8.GetBytes($body);
$stream = $request.GetRequestStream()
$stream.Write($bytes, 0, $bytes.Length);
$stream.Close();

$request.GetResponse();

Скорее всего, это связано с перенаправлением, как сказал pfx, вы также можете сделать MaximumRedirection 0 и поймать ошибку. Таким образом вы можете получить перенаправленный URL-адрес и попробовать еще раз.

Другие вопросы по тегам