Powershell System.Net.WebClient身份验证

时间:2012-10-15 14:35:32

标签: http authentication powershell webclient

尝试从受保护的HTTP源下载文件时使用以下代码返回401 Unauthorized:

$pfile = "\\some\local\leaf\path"
$user = "MyUserName"

$pwdIn = read-host -assecurestring | convertfrom-securestring | out-file $pfile
$pwdOut = get-content $pFile| convertto-securestring

$url="http://path.to/file"
$file = "\\localpath\to\file"
$webclient = new-object System.Net.WebClient
$webclient.Credentials = new-object System.Net.NetworkCredential($user, $pwdOut)
$webclient.DownloadFile($url,$file)

所以跳过写密码文件的步骤如下:

$pwd = read-host -assecurestring 
...
$webclient.Credentials = new-object System.Net.NetworkCredential($user, $pwd)

但是,跳过securestring创建工作正常:

 $pwd = read-host
 ...
 $webclient.Credentials = new-object System.Net.NetworkCredential($user, $pwd)

以上代码不会返回任何其他错误。我在顶部测试原始代码版本时验证了目标密码文件的存在性和明显的结构有效性。整个代码在单个脚本中,因此convertto和convertfrom在执行期间具有相同的环境。我在x86和64bit PowerShell中尝试了这个。

事实上,我甚至可以将安全字符串转换回正确的基本字符串,并将其与WebClient一起使用:

$pwdtmp = get-content $pFile| convertto-securestring
$pwdOut = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($pwdtmp))
$webclient.Credentials = new-object System.Net.NetworkCredential($user, $pwdOut)

因此,问题必须是使用SecureString和System.Net.NetworkCredential类,但是http://msdn.microsoft.com/en-us/library/system.net.networkcredential.aspx,以及我发现的一些例子表明SecureString应该作为第二个参数。

在撰写这篇文章时,我实际上找到了一个解决方案:

$user = "user"
$pwd = read-host -assecurestring
$creds = New-Object System.Management.Automation.PSCredential `
     -ArgumentList $user, $pwd  
$webclient.Credentials = new-object System.Net.NetworkCredential($user, $Creds.GetNetworkCredential().Password)
$webclient.DownloadFile($url,$file)

但是没有解释为什么SecureString类型不起作用,而PSCredential.Password确实如此。执行$ creds | gm清楚地表明$ creds.Password实际上也是一个SecureString:

  

TypeName:System.Management.Automation.PSCredential

     

名称成员类型定义

     

---- ---------- ---------- Equals方法bool Equals(System.Object obj)
  GetHashCode方法int GetHashCode()
  GetNetworkCredential Method System.Net.NetworkCredential   GetNetworkCredential()GetType方法类型GetType()   ToString方法字符串ToString()
  密码属性System.Security.SecureString密码   {获得;}

是什么给出了?

1 个答案:

答案 0 :(得分:7)

您可能正在使用早期版本的.Net Framework中的System.Net.NetworkCredential。接受SecureString的构造函数重载是在.Net 4.0中引入的。如果将SecureString传递给接受字符串的构造函数,那么powershell会将SecureString转换为字符串,该字符串将呈现字符串“System.Security.SecureString”的值。你可以测试一些事情:

  1. 调用构造函数,然后查看它的password属性以查看值是什么。如果我的假设是正确的,它将是“System.Security.SecureString”。

  2. 查看您正在使用的.Net Framework版本:

    $ PSVersionTable.CLRVersion

  3. 查询对象以查看它具有的构造函数:

    一个。从Jeffrey Snover复制并粘贴此function

    湾调用函数:

    get-Constructor system.net.networkcredential

  4. 从下面的输出中可以看出(我使用的是.net 2.0) - 没有接受SecureString的重载:

    NetworkCredential(
    )
    NetworkCredential(
        String userName,
        String password,
    )
    NetworkCredential(
        String userName,
        String password,
        String domain,
    )
    
相关问题