使用Invoke-WebRequest和用户名和密码在GitHub API上进行基本身份验证

Sha*_*tin 108 powershell basic-authentication github-api

初步问题

使用cURL,我们可以使用HTTP Web请求传递用户名,如下所示:

$ curl -u <your_username> https://api.github.com/user
Run Code Online (Sandbox Code Playgroud)

-u标志接受用于身份验证的用户名,然后cURL将请求密码.cURL示例用于使用GitHub Api进行基本身份验证.

我们如何同样传递用户名和密码以及Invoke-WebRequest?最终目标是在GitHub API中使用基本身份验证的PowerShell.

编辑(这是什么工作)

Notes来自客户端的Wikipedia on Basic Auth.

将用户名和密码合并为一个字符串 username:password

$user = "shaunluttin"
$pass = "super-strong-alpha-numeric-symbolic-long-password"
$pair = "${user}:${pass}"
Run Code Online (Sandbox Code Playgroud)

将字符串编码为Base64的RFC2045-MIME变体,但不限于76个字符/行.

$bytes = [System.Text.Encoding]::ASCII.GetBytes($pair)
$base64 = [System.Convert]::ToBase64String($bytes)
Run Code Online (Sandbox Code Playgroud)

创建Auth值作为方法,空格,然后编码对 Method Base64String

$basicAuthValue = "Basic $base64"
Run Code Online (Sandbox Code Playgroud)

创建标题 Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

$headers = @{ Authorization = $basicAuthValue }
Run Code Online (Sandbox Code Playgroud)

调用Web请求

Invoke-WebRequest -uri "https://api.github.com/user" -Headers $headers
Run Code Online (Sandbox Code Playgroud)

感谢@briantist的帮助!

讨论

PowerShell版本比cURL版本更冗长.这是为什么?@briantist指出GitHub打破了RFC并且PowerShell坚持使用它.这是否意味着cURL也打破了标准?

bri*_*ist 120

我在这里假设基本身份验证.

$cred = Get-Credential
Invoke-WebRequest -Uri 'https://whatever' -Credential $cred
Run Code Online (Sandbox Code Playgroud)

您可以通过其他方式(Import-Clixml等)获取您的凭证,但它必须是一个[PSCredential]对象.

根据评论进行编辑:

GitHub正在打破RFC,因为他们在您提供链接中解释:

API支持RFC2617中定义的基本身份验证,但略有不同.主要区别在于RFC要求使用401 Unauthorized响应来回答未经身份验证的请求.在许多地方,这将公开用户数据的存在.相反,GitHub API以404 Not Found响应.这可能会导致假定401 Unauthorized响应的HTTP库出现问题.解决方案是手动制作Authorization标头.

PowerShell的 Invoke-WebRequest我所知,在发送凭据之前等待401响应,而且由于GitHub从未提供凭据,因此永远不会发送您的凭据.

手动构建标头

相反,你必须自己创建基本的auth标头.

基本身份验证采用由冒号分隔的用户名和密码组成的字符串,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
Run Code Online (Sandbox Code Playgroud)

你可以结合一些字符串连接,但我想打破它以使其更清晰.

  • 如果也尝试针对 Visual Studio Team Services REST API 进行身份验证,则需要手动构建标头 (2认同)

小智 36

用这个:

$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
Run Code Online (Sandbox Code Playgroud)

  • 对我不起作用。根据 Fiddler 的说法,没有添加标头。 (2认同)

kar*_*cki 16

如果有人需要单衬:

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


小智 9

我必须这样做才能使其正常工作:

$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
Run Code Online (Sandbox Code Playgroud)


小智 7

这是使用 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/"
Run Code Online (Sandbox Code Playgroud)


Leo*_*ngs 5

Invoke-WebRequest遵循@briantist指出的RFC2617,但是有些系统(例如,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 "..."
Run Code Online (Sandbox Code Playgroud)

这将首次发送无效的标头,由于-Credentials覆盖Authorization标头,第二个请求中的有效凭证将替换该标头。

经过Powershell 5.1测试


Sha*_*tin 5

这对于我们的特殊情况是有效的。

注释来自Wikipedia on Basic Auth from the Client Side。感谢@briantist 的回答提供的帮助!

将用户名和密码组合成一个字符串username:password

$user = "shaunluttin"
$pass = "super-strong-alpha-numeric-symbolic-long-password"
$pair = "${user}:${pass}"
Run Code Online (Sandbox Code Playgroud)

将字符串编码为 Base64 的 RFC2045-MIME 变体,但不限于 76 个字符/行。

$bytes = [System.Text.Encoding]::ASCII.GetBytes($pair)
$base64 = [System.Convert]::ToBase64String($bytes)
Run Code Online (Sandbox Code Playgroud)

创建 Auth 值作为方法、空格,然后是编码对Method Base64String

$basicAuthValue = "Basic $base64"
Run Code Online (Sandbox Code Playgroud)

创建标题Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

$headers = @{ Authorization = $basicAuthValue }
Run Code Online (Sandbox Code Playgroud)

调用网络请求

Invoke-WebRequest -uri "https://api.github.com/user" -Headers $headers
Run Code Online (Sandbox Code Playgroud)

PowerShell 版本比 cURL 版本更详细。这是为什么?@briantist 指出 GitHub 正在打破 RFC,而 PowerShell 却坚持它。这是否意味着 cURL 也违反了标准?