Utilizzare Invoke-WebRequest con un nome utente e una password per l'autenticazione di base sull'API GitHub


127

Con cURL, possiamo trasmettere un nome utente con una richiesta Web HTTP come segue:

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

Il -uflag accetta un nome utente per l'autenticazione, quindi cURL richiederà la password. L'esempio cURL è per l' autenticazione di base con l'API GitHub .

Come passiamo allo stesso modo un nome utente e una password insieme a Invoke-WebRequest? L'obiettivo finale è quello di utilizzare PowerShell con l'autenticazione di base nell'API GitHub.


$ pair dovrebbe essere $pair = "$($user):$($pass)"Controlla la risposta approvata. Stavo usando quanto sopra e mi ha dato troppo dolore
Bhavjot il

Nessuna delle soluzioni che suggeriscono l' -Credentialapproccio funziona come l'intestazione auth corretta non viene generata quando viene effettuata la richiesta.
StingyJack,

@Shaun Luttin - Questa è una domanda ..... e un sito di risposta, non un sito di domande e risposte. Questo utente preferirebbe vedere una domanda quanto più breve possibile e risposte diverse da quelle che funzionavano per la tua situazione particolare, ma non dovendo leggerlo due volte (una volta nella domanda modificata, ora arriva QuestionAnswer e poi di nuovo nelle risposte). Se la preoccupazione era la risposta che ti aiutava a non essere il più vicino alla domanda, StackExchange ha funzionalità per portare la risposta migliore / accettata al più vicino possibile alla domanda.
user66001,

1
@ user66001 Grazie per il feedback. Ho spostato la mia risposta alla domanda nella sua risposta per riferimento futuro. Penso che questo sia un miglioramento.
Shaun Luttin,

@ShaunLuttin - Ottima idea! :)
user66001,

Risposte:


147

Sto assumendo qui l'autenticazione di base.

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

Puoi ottenere le tue credenziali con altri mezzi ( Import-Clixml, ecc.), Ma deve essere un [PSCredential]oggetto.

Modifica in base ai commenti:

GitHub sta rompendo RFC come spiegano nel link che hai fornito :

L'API supporta l'autenticazione di base come definito in RFC2617 con alcune lievi differenze. La differenza principale è che RFC richiede risposte non autenticate con 401 risposte non autorizzate. In molti luoghi, ciò rivelerebbe l'esistenza dei dati dell'utente. Invece, l'API GitHub risponde con 404 Not Found. Ciò può causare problemi per le librerie HTTP che assumono una risposta 401 non autorizzata. La soluzione è creare manualmente l'intestazione dell'autorizzazione.

Per quanto ne so, Powershell Invoke-WebRequestattende una risposta 401 prima di inviare le credenziali e poiché GitHub non ne fornisce mai una, le tue credenziali non verranno mai inviate.

Costruisci manualmente le intestazioni

Dovrai invece creare tu stesso le intestazioni di autenticazione di base.

L'autenticazione di base accetta una stringa composta da nome utente e password separati da due punti user:passe quindi invia il risultato con codifica Base64.

Codice come questo dovrebbe funzionare:

$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

Potresti combinare un po 'della concatenazione di stringhe ma volevo risolverlo per renderlo più chiaro.


1
Come ho detto, funziona per l'autenticazione di base, ma non so quale tipo di autenticazione utilizza l'API GitHub. Puoi pubblicare alcuni dettagli su ciò che è previsto e ciò potrebbe aiutarci a risolvere il problema.
Briantist,

1
Ah, sembra che GitHub non stia seguendo (per sua stessa ammissione) RFC, ma Powershell lo è. Ho modificato la risposta con ulteriori informazioni e una soluzione alternativa.
Briantist,

1
Sì, se hai intenzione di fare un sacco di questo tipo di chiamate, ti consiglio di racchiuderlo in una funzione. Come ho detto mi è scoppiata tutti i pezzi per la chiarezza, ma si poteva fare tutto su una riga (sarebbe solo essere disordinato).
Briantist

1
@Aref, dovresti pubblicare una nuova domanda con il codice che stai utilizzando. Se lo fai e fammi sapere, darò un'occhiata.
Briantist

1
Sarà necessario compilare manualmente le intestazioni se si tenta di eseguire l'autenticazione anche con l'API REST di Visual Studio Team Services
Brent Robinson,

44

Usa questo:

$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

Per qualche motivo la risposta selezionata non ha funzionato per me quando la utilizzavo su TFS vNext, ma questa ha funzionato. Molte grazie!
Tybs,

La risposta selezionata non ha funzionato per l'esecuzione di un runbook PowerShell su azzurro per avviare un processo attivato, ma questa risposta ha funzionato.
Sam

7

Ho dovuto farlo per farlo funzionare:

$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

6

Invoke-WebRequestsegue RFC2617 come notato da @briantist, tuttavia ci sono alcuni sistemi (ad esempio JFrog Artifactory) che consentono l'uso anonimo in caso di Authorizationintestazione assente, ma risponderanno 401 Forbiddense l'intestazione contiene credenziali non valide.

Questo può essere usato per innescare la 401 Forbiddenrisposta e mettersi -Credentialsal lavoro.

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

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

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

Questo invierà per la prima volta l'intestazione non valida, che verrà sostituita con le credenziali valide nella seconda richiesta poiché -Credentialssovrascrive l' Authorizationintestazione.

Testato con Powershell 5.1


5

Se qualcuno avesse bisogno di una fodera:

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

2

un altro modo è utilizzare certutil.exe per salvare nome utente e password in un file, ad esempio in.txt come nome utente: password

certutil -encode in.txt out.txt

Ora dovresti essere in grado di utilizzare il valore di autenticazione da out.txt

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

2

So che questo è un po 'fuori dalla richiesta originale dei PO, ma mi sono imbattuto in questo mentre cercavo un modo per utilizzare Invoke-WebRequest contro un sito che richiede l'autenticazione di base.

La differenza è che non volevo registrare la password nello script. Invece, volevo chiedere al runner dello script le credenziali per il sito.

Ecco come l'ho gestito

$creds = Get-Credential

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

Invoke-WebRequest -Uri $URL -Credential $basicCreds

Il risultato è che il runner di script viene richiesto con una finestra di dialogo di login per l'U / P, quindi Invoke-WebRequest è in grado di accedere al sito con tali credenziali. Questo funziona perché $ Creds.Password è già una stringa crittografata.

Spero che questo aiuti qualcuno alla ricerca di una soluzione simile alla domanda precedente ma senza salvare il nome utente o PW nello script


0

Questo è ciò che ha funzionato per la nostra situazione particolare.

Le note provengono da Wikipedia su Auth di base dal lato client . Grazie alla risposta di @ briantist per l'aiuto!

Combina nome utente e password in un'unica stringa username:password

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

Codifica la stringa nella variante RFC2045-MIME di Base64, tranne non limitato a 76 char / line.

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

Creare il valore Auth come metodo, uno spazio e quindi la coppia codificata Method Base64String

$basicAuthValue = "Basic $base64"

Crea l'intestazione Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

$headers = @{ Authorization = $basicAuthValue }

Richiamare la richiesta Web

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

La versione di PowerShell è più dettagliata della versione cURL. Perché? @briantist ha sottolineato che GitHub sta infrangendo l'RFC e PowerShell si attiene ad esso. Ciò significa che anche cURL sta rompendo con lo standard?

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.