0

注: ここでは PowerShell V3.0 を使用できません。それ以外の場合は、Invoke-WebRequest を使用して幸せな生活を送ることになります。

HTTP-Basic 認証済みリソースにデータを POST する必要がある PowerShell V2.0 スクリプトがあります。ユーザーのパスワードを知りたくない、または知る必要のないスクリプトの目的のために、PSCredentials オブジェクト (PromptForCredential から返される) を HttpWebRequest で使用する NetworkCredential に変換したいだけです。

$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) コンストラクターがあると言われていますが、ユーザーの資格情報は username: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 を String に適切に変換する方法」に基づいて、次の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 でエンコードされた正しい「username:password」文字列を取得できます。

于 2013-09-24T07:20:55.920 に答える