Verwenden Sie Invoke-WebRequest mit einem Benutzernamen und einem Kennwort für die grundlegende Authentifizierung auf der GitHub-API

127

Mit cURL können wir einen Benutzernamen mit einer HTTP-Webanforderung wie folgt übergeben:

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

Das -uFlag akzeptiert einen Benutzernamen zur Authentifizierung, und dann fordert cURL das Kennwort an. Das cURL-Beispiel ist für die Standardauthentifizierung mit der GitHub-API .

Wie übergeben wir in ähnlicher Weise einen Benutzernamen und ein Passwort zusammen mit Invoke-WebRequest? Das ultimative Ziel ist es, PowerShell mit Standardauthentifizierung in der GitHub-API zu verwenden.

Shaun Luttin
quelle
$ pair sollte sein $pair = "$($user):$($pass)"Überprüfen Sie die genehmigte Antwort. Ich benutzte das oben genannte und es gab mir zu viel Schmerz
Bhavjot
Keine der Lösungen, die vorschlagen, dass der -CredentialAnsatz als korrekter Authentifizierungsheader funktioniert, wird bei der Anforderung nicht generiert.
StingyJack
@Shaun Luttin - Dies ist eine Frage ..... und Antwortseite, keine Frage Antwort Seite. Dieser eine Benutzer würde es vorziehen, eine prägnante Frage und Antwort zu sehen, die nicht für Ihre spezielle Situation geeignet ist, diese aber nicht zweimal lesen muss (einmal in der bearbeiteten Frage, jetzt kommt QuestionAnswer und dann wieder in Antworten). Wenn das Problem die Antwort war, die Ihnen geholfen hat, der Frage nicht am nächsten zu kommen, verfügt StackExchange über Funktionen, mit denen die beste / akzeptierte Antwort der Frage bereits so nahe wie möglich gebracht werden kann.
user66001
1
@ user66001 Vielen Dank für das Feedback. Ich habe meine fragliche Antwort zur späteren Bezugnahme auf eine eigene Antwort verschoben. Ich denke, das ist eine Verbesserung.
Shaun Luttin
@ShaunLuttin - Tolle Idee! :)
user66001

Antworten:

147

Ich gehe hier von einer Standardauthentifizierung aus.

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

Sie können Ihren Berechtigungsnachweis auf andere Weise ( Import-Clixmlusw.) erhalten, es muss sich jedoch um ein [PSCredential]Objekt handeln.

Bearbeiten basierend auf Kommentaren:

GitHub bricht RFC, wie in dem von Ihnen angegebenen Link erläutert :

Die API unterstützt die in RFC2617 definierte Standardauthentifizierung mit einigen geringfügigen Unterschieden. Der Hauptunterschied besteht darin, dass für den RFC nicht authentifizierte Anforderungen mit 401 nicht autorisierten Antworten beantwortet werden müssen. An vielen Stellen würde dies das Vorhandensein von Benutzerdaten offenlegen. Stattdessen antwortet die GitHub-API mit 404 Not Found. Dies kann Probleme für HTTP-Bibliotheken verursachen, die eine nicht autorisierte Antwort von 401 annehmen. Die Lösung besteht darin, den Autorisierungsheader manuell zu erstellen.

Powershell's Invoke-WebRequestwartet meines Wissens auf eine 401-Antwort, bevor die Anmeldeinformationen gesendet werden. Da GitHub niemals eine bereitstellt, werden Ihre Anmeldeinformationen niemals gesendet.

Erstellen Sie die Header manuell

Stattdessen müssen Sie die grundlegenden Auth-Header selbst erstellen.

Bei der Standardauthentifizierung wird eine Zeichenfolge verwendet, die aus dem durch einen Doppelpunkt getrennten Benutzernamen und dem Kennwort besteht, user:passund anschließend das Base64-codierte Ergebnis gesendet.

Code wie dieser sollte funktionieren:

$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

Sie könnten einen Teil der Zeichenfolgenverkettung kombinieren, aber ich wollte sie ausbrechen, um sie klarer zu machen.

Briantist
quelle
1
Wie gesagt, es funktioniert für die Standardauthentifizierung, aber ich weiß nicht, welche Art von Authentifizierung die GitHub-API verwendet. Sie könnten einige Details darüber veröffentlichen, was erwartet wird, und das könnte uns helfen, das Problem zu lösen.
Briantist
1
Ah, es scheint, dass GitHub (nach eigenen Angaben) nicht RFC folgt, Powershell jedoch. Ich habe die Antwort mit weiteren Informationen und einer Problemumgehung bearbeitet.
Briantist
1
Ja, wenn Sie viele dieser Anrufe tätigen, würde ich empfehlen, dies in eine Funktion zu packen. Wie gesagt, ich habe aus Gründen der Klarheit wirklich alle Teile herausgebrochen, aber Sie könnten alles in einer Zeile erledigen (es wäre einfach chaotisch).
Briantist
1
@Aref, du solltest eine neue Frage mit dem von dir verwendeten Code posten. Wenn Sie dies tun und mich darüber informieren, werde ich einen Blick darauf werfen.
Briantist
1
Sie müssen die Header manuell erstellen, wenn Sie versuchen, sich auch anhand der REST-API von Visual Studio Team Services zu authentifizieren
Brent Robinson,
44

Benutze das:

$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
quelle
Aus irgendeinem Grund funktionierte die ausgewählte Antwort bei Verwendung mit TFS vNext nicht, aber diese hat den Trick gemacht. Vielen Dank!
Tybs
Die ausgewählte Antwort funktionierte nicht zum Ausführen eines Powershell-Runbooks unter Azure, um einen ausgelösten Job zu initiieren, aber diese Antwort funktionierte.
Sam
7

Ich musste das tun, damit es funktioniert:

$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
quelle
6

Invoke-WebRequestfolgt dem RFC2617, wie @briantist feststellt, es gibt jedoch einige Systeme (z. B. JFrog Artifactory), die eine anonyme Verwendung ermöglichen, wenn der AuthorizationHeader fehlt, aber mit antworten401 Forbidden wenn der Header ungültige Anmeldeinformationen enthält.

Dies kann verwendet werden, um die 401 ForbiddenReaktion auszulösen und -Credentialsan die Arbeit zu gehen.

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

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

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

Dadurch wird der ungültige Header beim ersten Mal gesendet, der in der zweiten Anforderung durch die gültigen Anmeldeinformationen ersetzt wird, da der Header -Credentialsüberschrieben wirdAuthorization Header .

Getestet mit Powershell 5.1

Leonard Brünings
quelle
5

Wenn jemand einen Einzeiler brauchen würde:

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

Eine andere Möglichkeit ist die Verwendung von certutil.exe. Speichern Sie Ihren Benutzernamen und Ihr Passwort in einer Datei, z. B. in.txt, als Benutzername: Passwort

certutil -encode in.txt out.txt

Jetzt sollten Sie in der Lage sein, den Auth-Wert aus out.txt zu verwenden

$headers = @{ Authorization = "Basic $((get-content out.txt)[1])" }
Invoke-WebRequest -Uri 'https://whatever' -Headers $Headers
Mayursharma
quelle
1

Ich weiß, dass dies ein wenig von der ursprünglichen Anforderung des OP abweicht, aber ich bin darauf gestoßen, als ich nach einer Möglichkeit gesucht habe, Invoke-WebRequest für eine Site zu verwenden, die eine grundlegende Authentifizierung erfordert.

Der Unterschied ist, ich wollte das Passwort nicht im Skript aufzeichnen. Stattdessen wollte ich den Skript-Runner zur Eingabe von Anmeldeinformationen für die Site auffordern.

So habe ich damit umgegangen

$creds = Get-Credential

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

Invoke-WebRequest -Uri $URL -Credential $basicCreds

Das Ergebnis ist, dass der Skript-Runner mit einem Anmeldedialog für das U / P aufgefordert wird. Invoke-WebRequest kann dann mit diesen Anmeldeinformationen auf die Site zugreifen. Dies funktioniert, da $ Creds.Password bereits eine verschlüsselte Zeichenfolge ist.

Ich hoffe, dies hilft jemandem, der nach einer ähnlichen Lösung für die obige Frage sucht, ohne jedoch den Benutzernamen oder PW im Skript zu speichern

Ernest Correale
quelle
0

Dies hat für unsere besondere Situation funktioniert.

Notizen stammen von Wikipedia zu Basic Auth von der Client-Seite . Vielen Dank an @ briantist's Antwort für die Hilfe!

Kombinieren Sie den Benutzernamen und das Passwort zu einer einzigen Zeichenfolge username:password

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

Codieren Sie die Zeichenfolge in die RFC2045-MIME-Variante von Base64, außer nicht auf 76 Zeichen / Zeile beschränkt.

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

Erstellen Sie den Auth-Wert als Methode, Leerzeichen und dann als codiertes Paar Method Base64String

$basicAuthValue = "Basic $base64"

Erstellen Sie den Header Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

$headers = @{ Authorization = $basicAuthValue }

Rufen Sie die Webanforderung auf

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

Die PowerShell-Version ist ausführlicher als die cURL-Version. Warum ist das so? @briantist wies darauf hin, dass GitHub den RFC bricht und PowerShell daran festhält. Bedeutet das, dass cURL auch mit dem Standard bricht?

Shaun Luttin
quelle