Użyj Invoke-WebRequest z nazwą użytkownika i hasłem do podstawowego uwierzytelniania w interfejsie API GitHub

127

Za pomocą cURL możemy przekazać nazwę użytkownika z żądaniem HTTP w następujący sposób:

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

-uFlagi przyjmuje nazwę użytkownika do uwierzytelniania, a następnie cURL poprosi hasło. Przykład cURL dotyczy uwierzytelniania podstawowego za pomocą interfejsu API GitHub .

W jaki sposób podobnie przekazujemy nazwę użytkownika i hasło wraz z Invoke-WebRequest? Ostatecznym celem jest korzystanie z programu PowerShell z uwierzytelnianiem podstawowym w interfejsie API GitHub.

Shaun Luttin
źródło
$ pair powinno być $pair = "$($user):$($pass)"Sprawdź zatwierdzoną odpowiedź.
Używałem
Żadne z rozwiązań, które sugerują takie -Credentialpodejście, nie działa, ponieważ poprawny nagłówek uwierzytelniania nie jest generowany po wysłaniu żądania.
StingyJack
@Shaun Luttin - To jest strona z pytaniami ..... i odpowiedziami, a nie witryna z pytaniami i odpowiedziami. Ten jeden użytkownik wolałby zobaczyć zwięzłe pytanie i odpowiedzi inne niż te, które działały w twojej konkretnej sytuacji, ale bez konieczności ich dwukrotnego czytania (raz w edytowanym pytaniu, teraz pojawi się pytanie Odpowiedź, a potem ponownie odpowiedzi). Jeśli obawa była odpowiedzią, która pomogła Ci nie być najbliżej pytania, StackExchange ma funkcjonalność, dzięki której najlepsza / zaakceptowana odpowiedź jest jak najbardziej zbliżona do pytania.
user66001
1
@ user66001 Dziękujemy za informację zwrotną. Przeniosłem swoją odpowiedź na pytanie do własnej odpowiedzi do późniejszego wykorzystania. Myślę, że to poprawa.
Shaun Luttin
@ShaunLuttin - Świetny pomysł! :)
user66001

Odpowiedzi:

147

Zakładam tutaj uwierzytelnianie podstawowe.

$cred = Get-Credential
Invoke-WebRequest -Uri 'https://whatever' -Credential $cred

Możesz uzyskać swoje dane uwierzytelniające w inny sposób ( Import-Clixmlitp.), Ale musi to być [PSCredential]obiekt.

Edytuj na podstawie komentarzy:

GitHub łamie RFC, jak wyjaśniają w podanym przez Ciebie łączu :

Interfejs API obsługuje uwierzytelnianie podstawowe zdefiniowane w dokumencie RFC2617 z kilkoma niewielkimi różnicami. Główną różnicą jest to, że RFC wymaga odpowiedzi na nieuwierzytelnione żądania za pomocą 401 nieautoryzowanych odpowiedzi. W wielu miejscach ujawniłoby to istnienie danych użytkownika. Zamiast tego interfejs API GitHub odpowiada komunikatem 404 Not Found. Może to powodować problemy dla bibliotek HTTP, które zakładają odpowiedź nieautoryzowaną 401. Rozwiązaniem jest ręczne utworzenie nagłówka Authorization.

Według Invoke-WebRequestmojej wiedzy, PowerShell czeka na odpowiedź 401 przed wysłaniem poświadczeń, a ponieważ GitHub nigdy ich nie dostarcza, twoje poświadczenia nigdy nie zostaną wysłane.

Ręcznie utwórz nagłówki

Zamiast tego będziesz musiał samodzielnie utworzyć podstawowe nagłówki uwierzytelniania.

Uwierzytelnianie podstawowe pobiera ciąg składający się z nazwy użytkownika i hasła oddzielone dwukropkiem, user:passa następnie wysyła wynik zakodowany w formacie Base64.

Kod taki powinien działać:

$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

Możesz łączyć niektóre konkatenacje ciągów, ale chciałem to przerwać, aby było jaśniejsze.

briantist
źródło
1
Jak powiedziałem, działa to w przypadku uwierzytelniania podstawowego, ale nie wiem, jakiego rodzaju uwierzytelniania używa API GitHub. Możesz opublikować szczegółowe informacje o oczekiwaniach, które mogą pomóc nam rozwiązać problem.
briantist
1
Ach, wygląda na to, że GitHub (jak sami przyznają) nie przestrzega RFC, ale Powershell tak. Zmieniłem odpowiedź, podając więcej informacji i obejście.
briantist
1
Tak, jeśli zamierzasz wykonywać wiele takich wywołań, polecam zawarcie tego w funkcji. Jak powiedziałem, że naprawdę wybuchła wszystkie kawałki dla jasności, ale mógłby zrobić to wszystko w jednej linii (byłoby to po prostu brudny).
briantist
1
@Aref, powinieneś zadać nowe pytanie z kodem, którego używasz. Jeśli to zrobisz i dasz mi znać, przyjrzę się.
briantist
1
Będziesz musiał ręcznie utworzyć nagłówki, jeśli próbujesz uwierzytelnić się w interfejsie API REST usług Visual Studio Team Services
Brent Robinson
44

Użyj tego:

$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
źródło
Z jakiegoś powodu wybrana odpowiedź nie działała dla mnie podczas używania jej na TFS vNext, ale ta załatwiła sprawę. Wielkie dzięki!
Tybs
Wybrana odpowiedź nie działała w przypadku uruchamiania elementu Runbook programu PowerShell na platformie Azure w celu zainicjowania wyzwalanego zadania, ale ta odpowiedź zadziałała.
Sam
7

Musiałem to zrobić, aby zadziałało:

$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
źródło
6

Invoke-WebRequestjest zgodny z RFC2617, jak zauważył @briantist, jednak istnieją pewne systemy (np. JFrog Artifactory), które pozwalają na anonimowe użycie, jeśli Authorizationnagłówek jest nieobecny, ale odpowiedzą, 401 Forbiddenjeśli nagłówek zawiera nieprawidłowe poświadczenia.

Można to wykorzystać do wyzwolenia 401 Forbidden odpowiedzi i zabrania się -Credentialsdo pracy.

$login = Get-Credential -Message "Enter Credentials for Artifactory"

                              #Basic foo:bar
$headers = @{ Authorization = "Basic Zm9vOmJhcg==" }  

Invoke-WebRequest -Credential $login -Headers $headers -Uri "..."

Spowoduje to wysłanie nieprawidłowego nagłówka za pierwszym razem, który zostanie zastąpiony prawidłowymi danymi uwierzytelniającymi w drugim żądaniu, ponieważ -Credentialszastępuje Authorizationnagłówek.

Przetestowano z Powershell 5.1

Leonard Brünings
źródło
5

Gdyby ktoś potrzebował jednej wkładki:

iwr -Uri 'https://api.github.com/user' -Headers @{ Authorization = "Basic "+ [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("user:pass")) }
karolberezicki
źródło
2

innym sposobem jest użycie certutil.exe, zapisz swoją nazwę użytkownika i hasło w pliku np. in.txt jako nazwa użytkownika: hasło

certutil -encode in.txt out.txt

Teraz powinieneś móc użyć wartości auth z out.txt

$headers = @{ Authorization = "Basic $((get-content out.txt)[1])" }
Invoke-WebRequest -Uri 'https://whatever' -Headers $Headers
mayursharma
źródło
2

Wiem, że jest to trochę odbiegające od pierwotnego żądania OP, ale natknąłem się na to, szukając sposobu na użycie Invoke-WebRequest przeciwko witrynie wymagającej podstawowego uwierzytelnienia.

Różnica polega na tym, że nie chciałem zapisywać hasła w skrypcie. Zamiast tego chciałem poprosić program uruchamiający skrypty o dane uwierzytelniające dla witryny.

Oto jak sobie z tym poradziłem

$creds = Get-Credential

$basicCreds = [pscredential]::new($Creds.UserName,$Creds.Password)

Invoke-WebRequest -Uri $URL -Credential $basicCreds

W rezultacie program uruchamiający skrypt jest monitowany o okno dialogowe logowania dla U / P, a następnie Invoke-WebRequest może uzyskać dostęp do witryny przy użyciu tych poświadczeń. To działa, ponieważ $ Cred.Password jest już zaszyfrowanym ciągiem.

Mam nadzieję, że pomoże to komuś szukającemu podobnego rozwiązania powyższego pytania, ale bez zapisywania nazwy użytkownika lub PW w skrypcie

Ernest Correale
źródło
0

To właśnie zadziałało w naszej szczególnej sytuacji.

Notatki pochodzą z Wikipedii na temat uwierzytelniania podstawowego po stronie klienta . Dziękuję @ briantist za pomoc!

Połącz nazwę użytkownika i hasło w jeden ciąg username:password

$user = "shaunluttin"
$pass = "super-strong-alpha-numeric-symbolic-long-password"
$pair = "${user}:${pass}"

Zakoduj ciąg zgodnie z wariantem RFC2045-MIME Base64, z wyjątkiem nie ograniczania się do 76 znaków / linii.

$bytes = [System.Text.Encoding]::ASCII.GetBytes($pair)
$base64 = [System.Convert]::ToBase64String($bytes)

Utwórz wartość Auth jako metodę, spację, a następnie zakodowaną parę Method Base64String

$basicAuthValue = "Basic $base64"

Utwórz nagłówek Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

$headers = @{ Authorization = $basicAuthValue }

Wywołaj żądanie sieciowe

Invoke-WebRequest -uri "https://api.github.com/user" -Headers $headers

Wersja tego programu PowerShell jest bardziej szczegółowa niż wersja cURL. Dlaczego? @briantist wskazał, że GitHub łamie RFC i PowerShell się do tego trzyma. Czy to oznacza, że ​​cURL również łamie standardy?

Shaun Luttin
źródło