0

注意:我不能在这里使用 PowerShell V3.0,否则我会使用 Invoke-WebRequest 并过上幸福的生活。

我有一个 PowerShell V2.0 脚本,它需要将数据发布到经过 HTTP-Basic 身份验证的资源。出于脚本的目的,我不想或不需要知道用户的密码,我只想将 PSCredentials 对象(从 PromptForCredential 返回)转换为 NetworkCredential 以与 HttpWebRequest 一起使用。

$uri = "https://example.com/some/resource/"

# Get our user's credentials...
$defaultUsername = "Some Username"
$caption = "Authentication required"
$message = "A username and password is required for ${uri}"
#$target = $uri #<<--NOTE: This prepends $uri+"\" to the username.
#$target = "" #<<--NOTE: This prepends "\" to the username.
$target = $null #<<--NOTE: This still prepends "\" to the username.
$psCredential = $Host.UI.PromptForCredential($caption, $message, $defaultUsername, $target)

# Construct a CredentialCache for HttpWebRequest...
# NOTE: We need to delete the "domain part" of the username from the PSCrential.Username, otherwise we get "Something\Username"
$username = ($psCredential.Username).Split('\')[1]
$networkCredential = New-Object System.Net.NetworkCredential($username, [System.Security.SecureString]$psCredential.Password)
$credentialCache = New-Object System.Net.CredentialCache
$credentialCache.Add( (New-Object Uri($uri)), "Basic", $networkCredential)

#...
$request = New-Object System.Net.HttpWebRequest($uri)
$request.Credentials = $credentialCache
#...
[System.Net.HttpWebResponse]$response = [System.Net.HttpWebResponse]$request.GetResponse()

这当然会失败,但有以下例外:

Exception calling "GetResponse" with "0" argument(s):
"The remote server returned an error: (401) Unauthorized."

据称我们有一个 NetworkCredential(String userName, SecureString password) 构造函数,但用户的凭据以用户名:System.Security.SecureString 的形式到达服务器。

我缺少一些小细节吗?我是否需要解密 SecureString 并将其传递给 NetworkCredential(String userName, String password) 构造函数?

4

2 回答 2

0

我发现了问题... NetworkCredential(String userName, SecureString password) 构造函数仅从 .NET Framework 4.0 开始可用。当然 PowerShell 2.0 在 .NET 2.0 中运行。

虽然有一些方法可以让 PowerShell 2.0 在 .NET 4.0 中运行,但我不能随意更改运行时环境的配置。

相反,我走上了“不安全字符串”的道路。基于文章“如何正确地将 SecureString 转换为字符串”,我创建了这个 PowerShell 函数:

function Convert-To-Unsecure-String {
        Param(
            [Parameter(HelpMessage="The SecureString object to make a very unsecure String")]
            [ValidateNotNull()]
            [System.Security.SecureString]
            $securePassword
        )
        $unmanagedString = [System.IntPtr]::Zero
        try {
            $unmanagedString = [Runtime.InteropServices.Marshal]::SecureStringToGlobalAllocUnicode($securePassword);
            return [Runtime.InteropServices.Marshal]::PtrToStringUni($unmanagedString);
        }
        finally {
            [Runtime.InteropServices.Marshal]::ZeroFreeGlobalAllocUnicode($unmanagedString);
        }
}

并将原始示例的 NetworkCredential 构造函数替换为:

$networkCredential = New-Object System.Net.NetworkCredential($username, (Convert-To-Unsecure-String($psCredential.Password)) )

现在我在服务器上得到了正确的 base64 编码的“用户名:密码”字符串。

于 2013-09-24T07:20:55.920 回答
0

我遇到了同样的问题。我的修复非常简单。不要在用户名中包含域名。我试图连接到 JIRA 以运行 JQL。

不要这样做 $userName = Me@Mydomain; 或者 $userName=MyDomain/Me 但是这样做 $userName = Me

于 2015-10-13T14:54:31.687 回答