使用 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 用户。
$pair = "$($user):$($pass)"
检查批准的答案。我正在使用上面的,它给了我太多的痛苦
-Credential
方法的解决方案都不起作用,因为在发出请求时未生成正确的身份验证标头。
我在这里假设基本身份验证。
$cred = Get-Credential
Invoke-WebRequest -Uri 'https://whatever' -Credential $cred
您可以通过其他方式(Import-Clixml
等)获取您的凭证,但它必须是 [PSCredential]
对象。
根据评论编辑:
正如他们在 link you provided 中解释的那样,GitHub 正在破坏 RFC:
API 支持 RFC2617 中定义的基本身份验证,但有一些细微差别。主要区别在于 RFC 要求使用 401 Unauthorized 响应来回答未经身份验证的请求。在许多地方,这会泄露用户数据的存在。相反,GitHub API 以 404 Not Found 响应。这可能会导致假定 401 Unauthorized 响应的 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
您可以组合一些字符串连接,但我想将其分解以使其更清晰。
用这个:
$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
如果有人需要一个班轮:
iwr -Uri 'https://api.github.com/user' -Headers @{ Authorization = "Basic "+ [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("user:pass")) }
正如@briantist 所指出的,Invoke-WebRequest
遵循 RFC2617,但是如果 Authorization
标头不存在,某些系统(例如 JFrog Artifactory)允许匿名使用,但如果标头包含无效凭据,则会以 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 测试
credential
,则是否需要基本授权标头?根据您的回答,-credential
仅在它之前从 headers
获得 401
时才有效,因此必须有 basic foo:bar
以便它不是匿名的?
Authorization
标头触发 401
以使 -Credential
工作。
foo:bar
是正确的,我需要将其操作为 .eg foobar:bar
用于 auth header key
..
foo:bar
,那么您需要使用不同的东西。
我必须这样做才能让它工作:
$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
这是使用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/"
-Headers
参数需要 [string],[string]
的字典或哈希表。您实际上可以只定义一个数组 - 例如 @(Authorization = 'Basic ...')
就像他在这里所做的那样,powershell 会为您转换它
basic
与 digest
混合,后者在答案中与 credential
参数一起使用。
这对我们的特殊情况有效。
注释来自 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 则坚持使用它。这是否意味着 cURL 也违反了标准?
另一种方法是使用 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
我知道这与 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 已经是一个加密字符串。
我希望这可以帮助寻找上述问题的类似解决方案但没有在脚本中保存用户名或密码的人
不定期副业成功案例分享