Используйте Invoke-WebRequest с именем пользователя и паролем для базовой аутентификации в GitHub API.

127

С помощью cURL мы можем передать имя пользователя с помощью веб-запроса HTTP следующим образом:

$ curl -u <your_username> https://api.github.com/user

-uФлаг принимает имя пользователя для аутентификации, а затем Curl будет запрашивать пароль. Пример cURL предназначен для базовой аутентификации с помощью GitHub Api .

Как мы аналогичным образом передаем имя пользователя и пароль вместе с Invoke-WebRequest? Конечная цель - использовать PowerShell с базовой аутентификацией в API GitHub.

Шон Латтин
источник
$ pair должна быть $pair = "$($user):$($pass)"Проверить утвержденный ответ. Я использовал вышеупомянутое, и это доставляло мне слишком много боли
Бхавджот
Ни одно из решений, предлагающих такой -Credentialподход, не работает, поскольку правильный заголовок аутентификации не создается при выполнении запроса.
StingyJack
@Shaun Luttin - Это сайт вопросов и ответов, а не сайт ответов на вопросы. Этот пользователь предпочел бы видеть краткий возможный вопрос и ответы, отличные от того, что работает в вашей конкретной ситуации, но не должен читать это дважды (один раз в отредактированном вопросе, теперь войдите в ответ на вопрос, а затем снова в ответах). Если бы проблема заключалась в том, что ответ, который помог вам, не был бы наиболее близок к вопросу, StackExchange имеет функцию, позволяющую максимально приблизить лучший / принятый ответ к уже поставленному вопросу.
user66001
1
@ user66001 Спасибо за отзыв. Я переместил свой ответ на вопрос в отдельный ответ для дальнейшего использования. Думаю, это улучшение.
Шон Латтин
@ShaunLuttin - Отличная идея! :)
user66001

Ответы:

147

Я предполагаю здесь базовую аутентификацию.

$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

Вы можете объединить некоторые конкатенации строк, но я хотел разбить их, чтобы было понятнее.

briantist
источник
1
Как я уже сказал, он работает для обычной аутентификации, но я не знаю, какой тип аутентификации использует GitHub API. Вы можете опубликовать подробную информацию о том, что ожидается, и это может помочь нам решить проблему.
briantist
1
Ах, похоже, GitHub (по их собственному признанию) не следует RFC, а Powershell -. Я отредактировал ответ с дополнительной информацией и обходным путем.
briantist
1
Да, если вы собираетесь выполнять много таких вызовов, я бы рекомендовал обернуть это функцией. Как я уже сказал, я разбил все на части для ясности, но вы можете сделать все в одной строке (это было бы просто беспорядочно).
briantist
1
@Aref, вам следует опубликовать новый вопрос с использованием кода, который вы используете. Если вы это сделаете и дадите мне знать, я посмотрю.
briantist
1
При попытке аутентификации с помощью REST API Visual Studio Team Services вам также нужно будет вручную создать заголовки,
Брент Робинсон,
44

Использовать это:

$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
mfralou
источник
По какой-то причине выбранный ответ не сработал для меня при использовании его в TFS vNext, но этот сработал. Большое спасибо!
Tybs 01
Выбранный ответ не подходит для запуска модуля Runbook PowerShell в Azure для запуска триггерного задания, но этот ответ сработал.
Сэм
7

Мне пришлось сделать это, чтобы заставить его работать:

$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
livy111
источник
6

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

Леонард Брюнингс
источник
5

Если кому-то понадобится один лайнер:

iwr -Uri 'https://api.github.com/user' -Headers @{ Authorization = "Basic "+ [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("user:pass")) }
karolberezicki
источник
2

Другой способ - использовать certutil.exe, сохранить ваше имя пользователя и пароль в файле, например, in.txt как имя пользователя: пароль

certutil -encode in.txt out.txt

Теперь вы можете использовать значение аутентификации из out.txt.

$headers = @{ Authorization = "Basic $((get-content out.txt)[1])" }
Invoke-WebRequest -Uri 'https://whatever' -Headers $Headers
mayursharma
источник
2

Я знаю, что это немного отличается от исходного запроса 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 в скрипте.

Эрнест Корреале
источник
0

Это то, что сработало в нашей конкретной ситуации.

Примечания взяты из Википедии о базовой аутентификации на стороне клиента . Спасибо ответу @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 также нарушает стандарт?

Шон Латтин
источник