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

时间:2015-01-14 20:10:15

标签: powershell github-api http-basic-authentication

初步问题

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

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

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

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

编辑(这是什么工作)

备注来自Wikipedia on Basic Auth from the Client Side

将用户名和密码合并为一个字符串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

感谢@briantist的帮助!

讨论

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

9 个答案:

答案 0 :(得分:105)

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

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

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

根据评论进行编辑:

GitHub正在破解RFC,因为他们在link you provided中解释:

  

API支持RFC2617中定义的基本身份验证   细微差别。主要区别在于RFC要求   401未经授权的未经认证的请求   响应。在许多地方,这将披露用户的存在   数据。相反,GitHub API以404 Not Found响应。这可能   假定401未授权的HTTP库会导致问题   响应。解决方案是手动制作Authorization标头。

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

手动构建标题

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

基本身份验证采用由冒号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 :(得分:32)

使用此:

configure
set service dns forwarding options address=/.bing.com/216.239.38.120
set service dns forwarding options address=/.ask.com/216.239.38.120
set service dns forwarding options address=/.duckduckgo.com/216.239.38.120
commit
save

答案 2 :(得分:5)

@ priantist指出,

Invoke-WebRequest遵循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进行测试

答案 3 :(得分:5)

如果某人需要一根衬纸:

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

答案 4 :(得分:2)

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

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

答案 5 :(得分:2)

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

答案 6 :(得分: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

答案 7 :(得分:1)

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

注释来自Wikipedia on Basic Auth from the Client Side。谢谢@briantist's answer的帮助!

将用户名和密码合并为一个字符串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也违反了标准?

答案 8 :(得分:0)

另一种方法是使用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