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

Use Invoke-WebRequest with a username and password for basic authentication on the GitHub API

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

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

-u 标志接受用户名进行身份验证,然后 cURL 将请求密码。 cURL 示例适用于 Basic authentication with the GitHub Api.

我们如何将用户名和密码与 Invoke-WebRequest 一起传递?最终目标是在 GitHub API.

中使用具有基本身份验证的用户 PowerShell

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

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

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

根据评论进行编辑:

正如他们在 link you provided:

中解释的那样,

GitHub 正在破坏 RFC

The API supports Basic Authentication as defined in RFC2617 with a few slight differences. The main difference is that the RFC requires unauthenticated requests to be answered with 401 Unauthorized responses. In many places, this would disclose the existence of user data. Instead, the GitHub API responds with 404 Not Found. This may cause problems for HTTP libraries that assume a 401 Unauthorized response. The solution is to manually craft the Authorization header.

据我所知,Powershell 的 Invoke-WebRequest 在发送凭据之前会等待 401 响应,并且由于 GitHub 从未提供过,因此您的凭据将永远不会被发送。

手动构建 headers

相反,您必须自己创建基本身份验证 headers。

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

您可以组合一些字符串连接,但我想将其分解以使其更清晰。

使用这个:

$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

Invoke-WebRequest 遵循@briantist 指出的 RFC2617,但是如果 Authorization header 不存在,有些系统(例如 JFrog Artifactory)允许匿名使用,但会响应使用 401 Forbidden 如果 header 包含无效凭据。

这可用于触发 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 "..."

这将在第一次发送无效的 header,由于 -Credentials 覆盖了 Authorization header,它将在第二次请求中被替换为有效凭据。

使用 Powershell 5.1 测试

我必须这样做才能让它工作:

$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

另一种方法是使用 certutil.exe 将您的用户名和密码保存在文件中,例如in.txt 作为 username:password

certutil -encode in.txt out.txt

现在您应该可以使用来自 out.txt

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

如果有人需要一个班轮:

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

我知道这有点偏离 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 已经是一个加密的字符串。

我希望这可以帮助那些寻找与上述问题类似的解决方案但没有在脚本中保存用户名或密码的人

这对我们的特定情况有效。

注释来自 Wikipedia on Basic Auth from the Client Side. Thank you to @briantist's answer 寻求帮助!

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

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

将字符串编码为 Base64 的 RFC2045-MIME 变体,除了不限于 76 char/line。

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

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

$basicAuthValue = "Basic $base64"

创建 header Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

$headers = @{ Authorization = $basicAuthValue }

调用 web-request

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

它的 PowerShell 版本比 cURL 版本更冗长。这是为什么? @briantist 指出 GitHub 破坏了 RFC,而 PowerShell 坚持使用它。这是否意味着 cURL 也违反了标准?

这是使用 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/"