Используйте Invoke-WebRequest с именем пользователя и паролем для базовой аутентификации в GitHub API
Начальный вопрос
С помощью cURL мы можем передать имя пользователя с помощью веб-запроса HTTP следующим образом:
$ curl -u <your_username> https://api.github.com/user
-u
Флаг принимает имя пользователя для аутентификации, а затем cURL запросит пароль. Пример cURL для базовой аутентификации с помощью GitHub Api.
Как мы также передаем имя пользователя и пароль вместе с Invoke-WebRequest? Конечной целью является использование PowerShell с базовой аутентификацией в GitHub API.
Редактировать (это то, что сработало)
Заметки взяты из Википедии о базовой аутентификации со стороны клиента.
Объедините имя пользователя и пароль в одну строку username:password
$user = "shaunluttin"
$pass = "super-strong-alpha-numeric-symbolic-long-password"
$pair = "${user}:${pass}"
Кодируйте строку в варианте Base64 RFC2045-MIME, за исключением не ограниченного 76 символами / строкой.
$bytes = [System.Text.Encoding]::ASCII.GetBytes($pair)
$base64 = [System.Convert]::ToBase64String($bytes)
Создайте значение Auth как метод, пробел, а затем закодированную пару Method Base64String
$basicAuthValue = "Basic $base64"
Создать заголовок Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
$headers = @{ Authorization = $basicAuthValue }
Вызвать веб-запрос
Invoke-WebRequest -uri "https://api.github.com/user" -Headers $headers
Спасибо @briantist за помощь!
обсуждение
Версия PowerShell более многословна, чем версия cURL. Это почему? @briantist отметил, что GitHub нарушает RFC, и PowerShell придерживается его. Означает ли это, что cURL также нарушает стандарт?
4 ответа
Я предполагаю базовую аутентификацию здесь.
$cred = Get-Credential
Invoke-WebRequest -Uri 'https://whatever' -Credential $cred
Вы можете получить свои учетные данные другими способами (Import-Clixml
и т. д.), но это должно быть [PSCredential]
объект.
Редактировать на основе комментариев:
GitHub нарушает RFC, как они объясняют по предоставленной вами ссылке:
API поддерживает базовую аутентификацию, как определено в RFC2617, с небольшими отличиями. Основное различие заключается в том, что RFC требует, чтобы на запросы, не прошедшие проверку подлинности, было получено 401 ответ. Во многих местах это раскрыло бы существование пользовательских данных. Вместо этого GitHub API отвечает 404 Not Found. Это может вызвать проблемы для библиотек HTTP, которые принимают 401 несанкционированный ответ. Решение состоит в том, чтобы вручную создать заголовок авторизации.
Powershell-х Invoke-WebRequest
насколько мне известно, ждет ответа 401 перед отправкой учетных данных, и, поскольку GitHub никогда не предоставляет их, ваши учетные данные никогда не будут отправлены.
Построить заголовки вручную
Вместо этого вам придется самостоятельно создавать основные заголовки аутентификации.
Обычная аутентификация принимает строку, состоящую из имени пользователя и пароля, разделенных двоеточием user:pass
и затем отправляет закодированный Base64 результат этого.
Код, подобный этому, должен работать:
$user = 'user'
$pass = 'pass'
$pair = "$($user):$($pass)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))
$basicAuthValue = "Basic $encodedCreds"
$Headers = @{
Authorization = $basicAuthValue
}
Invoke-WebRequest -Uri 'https://whatever' -Headers $Headers
Вы могли бы объединить некоторые из конкатенации строк, но я хотел разбить их, чтобы сделать их более понятными.
Использовать этот:
$root = 'REST_SERVICE_URL'
$user = "user"
$pass= "password"
$secpasswd = ConvertTo-SecureString $pass -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential($user, $secpasswd)
$result = Invoke-RestMethod $root -Credential $credential
Если кому-то понадобится один лайнер:
iwr -Uri 'https://api.github.com/user' -Headers @{ Authorization = "Basic "+ [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("user:pass")) }
Invoke-WebRequest
следует RFC2617, как отметил @briantist, однако есть некоторые системы (например, JFrog Artifactory), которые разрешают анонимное использование, если Authorization
заголовок отсутствует, но ответит 401 Forbidden
если заголовок содержит недействительные учетные данные.
Это может быть использовано для запуска 401 Forbidden
ответ и получить -Credentials
работать.
$login = Get-Credential -Message "Enter Credentials for Artifactory"
#Basic foo:bar
$headers = @{ Authorization = "Basic Zm9vOmJhcg==" }
Invoke-WebRequest -Credential $login -Headers $headers -Uri "..."
Это отправит неверный заголовок в первый раз, который будет заменен действительными учетными данными во втором запросе, так как -Credentials
переопределяет Authorization
заголовок.
Протестировано с Powershell 5.1
Я должен был сделать это, чтобы заставить это работать:
$pair = "$($user):$($pass)"
$encodedCredentials = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($Pair))
$headers = @{ Authorization = "Basic $encodedCredentials" }
Invoke-WebRequest -Uri $url -Method Get -Headers $headers -OutFile Config.html
Вот еще один способ использования WebRequest, надеюсь, он сработает для вас
$user = 'whatever'
$pass = 'whatever'
$secpasswd = ConvertTo-SecureString $pass -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential($user, $secpasswd)
$headers = @{ Authorization = "Basic Zm9vOmJhcg==" }
Invoke-WebRequest -Credential $credential -Headers $headers -Uri "https://dc01.test.local/"
Это то, что сработало в нашей конкретной ситуации.
Примечания взяты из Википедии о базовой аутентификации на стороне клиента. Спасибо ответу @briantist за помощь!
Объедините имя пользователя и пароль в одну строку username:password
$user = "shaunluttin"
$pass = "super-strong-alpha-numeric-symbolic-long-password"
$pair = "${user}:${pass}"
Кодируйте строку в RFC2045-MIME вариант Base64, за исключением 76 символов на строку.
$bytes = [System.Text.Encoding]::ASCII.GetBytes($pair)
$base64 = [System.Convert]::ToBase64String($bytes)
Создайте значение Auth как метод, пробел, а затем закодированную пару Method Base64String
$basicAuthValue = "Basic $base64"
Создайте заголовок Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
$headers = @{ Authorization = $basicAuthValue }
Сделать веб-запрос
Invoke-WebRequest -uri "https://api.github.com/user" -Headers $headers
Версия PowerShell более подробна, чем версия cURL. Почему это? @briantist указал, что GitHub нарушает RFC, а PowerShell придерживается его. Означает ли это, что cURL также нарушает стандарт?
Другой способ - использовать certutil.exe. Сохраните имя пользователя и пароль в файле, например, в.txt как имя пользователя: пароль.
certutil -encode in.txt out.txt
Теперь вы должны иметь возможность использовать значение auth из out.txt
$headers = @{ Authorization = "Basic $((get-content out.txt)[1])" }
Invoke-WebRequest -Uri 'https://whatever' -Headers $Headers
Я знаю, что это немного отличается от исходного запроса OP, но я столкнулся с этим, когда искал способ использовать Invoke-WebRequest против сайта, требующего базовой аутентификации.
Разница в том, что я не хотел записывать пароль в скрипт. Вместо этого я хотел запросить у исполнителя сценария учетные данные для сайта.
Вот как я с этим справился
$creds = Get-Credential
$basicCreds = [pscredential]::new($Creds.UserName,$Creds.Password)
Invoke-WebRequest -Uri $URL -Credential $basicCreds
В результате исполнителю сценария предлагается диалоговое окно входа в систему для U/P, после чего Invoke-WebRequest может получить доступ к сайту с этими учетными данными. Это работает, потому что $Creds.Password уже является зашифрованной строкой.
Надеюсь, это поможет кому-то, кто ищет аналогичное решение для вышеуказанного вопроса, но без сохранения имени пользователя или PW в скрипте.