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


127

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

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

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

我们如何类似地将用户名和密码与Invoke-WebRequest一起传递?最终目标是在GitHub API中使用基本身份验证来使用PowerShell。


$ pair应该是$pair = "$($user):$($pass)"检查批准的答案。我使用了上面的方法,这让我感到非常痛苦
Bhavjot

由于提出-Credential请求时未生成正确的auth标头,因此没有任何建议该方法的解决方案。
StingyJack

@Shaun Luttin-这是一个问题.....和答案的站点,而不是问题答案的站点。该用户希望看到简洁的问题和答案,而不是针对您的特定情况所用的内容,但不必两次阅读(在已编辑的Question中,现在请QuestionAnswer,然后再在答案中)。如果关注的问题是可以帮助您的答案,而不是最接近问题的内容,则StackExchange具有使最佳/可接受的答案尽可能接近问题的功能。
user66001

1
@ user66001感谢您的反馈。我已将问题的答案移至其自己的答案,以供以后参考。我认为这是一种改进。
Shaun Luttin

@ShaunLuttin-好主意!:)
user66001

Answers:


147

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

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

您可以通过其他方式获得证书(Import-Clixml等),但这必须是一个[PSCredential]对象。

根据评论进行编辑:

GitHub违反了RFC,正如他们在您提供链接中解释的那样

该API支持RFC2617中定义的基本身份验证,但有一些细微差别。主要区别在于RFC要求使用未经授权的401响应来回答未经身份验证的请求。在许多地方,这将揭示用户数据的存在。取而代之的是,GitHub API会以404 Not Found响应。这可能会导致HTTP库出现401未经授权的响应的问题。解决方案是手动制作Authorization标头。

Invoke-WebRequest我所知,Powershell 会在发送凭据之前等待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

您可以合并一些字符串连接,但是我想对其进行分解以使其更清晰。


1
正如我所说的,它适用于基本身份验证,但是我不知道GitHub API使用哪种身份验证。您可以发布一些有关预期的细节,这可能有助于我们解决问题。
briantist

1
啊,看来GitHub(根据他们自己的观点)不是遵循RFC,而是Powershell。我已经用更多信息和解决方法编辑了答案。
briantist

1
是的,如果您要进行许多此类调用,则建议将其包装在函数中。正如我说的那样,为了清晰起见,我确实分解了所有部分,但是您可以在一行上完成所有操作(这太混乱了)。
briantist

1
@Aref,您应该使用所使用的代码发布一个新问题。如果您愿意,请告诉我,我会看看。
briantist

1
如果也尝试通过Visual Studio Team Services REST API进行身份验证,则需要手动构建标头
Brent Robinson

44

用这个:

$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

由于某些原因,在TFS vNext上使用所选答案时,它对我不起作用,但是这个技巧就可以了。非常感谢!
Tybs

所选答案不适用于在Azure上运行Powershell Runbook来启动触发的作业,但是此答案确实有效。
山姆

7

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

$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-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 "..."

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

经过Powershell 5.1测试


5

如果有人需要一根衬板:

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

2

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

certutil -encode in.txt out.txt

现在您应该能够使用out.txt中的auth值

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

1

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

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


0

这是对我们的特定情况起作用的。

注释来自Wikipedia的客户端基本身份验证。感谢@briantist的帮助!

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

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

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

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

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

$basicAuthValue = "Basic $base64"

创建标题 Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

$headers = @{ Authorization = $basicAuthValue }

调用网络请求

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.