【问题标题】:Powershell System.Net.WebClient AuthenticationPowershell System.Net.WebClient 身份验证
【发布时间】:2012-10-05 13:28:48
【问题描述】:

使用以下代码尝试从受保护的 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)

但是,跳过安全字符串创建工作正常:

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

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

因此,问题一定是在 System.Net.NetworkCredential 类中使用 SecureString,但是 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:

类型名称:System.Management.Automation.PSCredential

名称成员类型定义

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

什么给了?

【问题讨论】:

  • 我猜 $Creds.GetNetworkCredential().Password 有效,因为它返回一个纯字符串。那么为什么安全字符串不起作用呢?

标签: http authentication powershell webclient


【解决方案1】:

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

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

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

    $PSVersionTable.CLRVersion

  3. 查询对象以查看它有哪些构造函数:

    一个。复制并粘贴来自 Jeffrey Snover 的 function

    b.调用函数:

    get-Constructor system.net.networkcredential

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

NetworkCredential(
)
NetworkCredential(
    String userName,
    String password,
)
NetworkCredential(
    String userName,
    String password,
    String domain,
)

【讨论】:

  • 感谢您的回答!我确实在这种环境中运行 .NET2。
猜你喜欢
  • 2010-11-05
  • 2010-11-15
  • 1970-01-01
  • 2015-08-27
  • 1970-01-01
  • 1970-01-01
  • 2020-05-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多