2012-10-15 56 views
3

在試圖從受保護的HTTP源下載文件使用下面的代碼返回401未經授權:PowerShell的System.Net.WebClient認證

$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和64位PowerShell中都試過了。

事實上,我甚至可以安全字符串轉換回用正確的基本字符串與Web客戶端使用它:

$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 |通用清楚地表明,$ creds.Password也是事實SecureString的:

類型名:System.Management.Automation.PSCredential

名稱MemberType定義

---- - --------- ----------等於方法bool等於(System.Object obj)
GetHashCode方法int GetHashCode()
GetNetworkCredential方法System.Net.NetworkCredential GetNetworkCredential() GetType方法類型GetType () ToString方法字符串的ToString()
Password屬性爲System.Security.SecureString密碼 {獲得;}

是怎麼回事?

+1

我猜$ Creds.GetNetworkCredential()。密碼的工作原理是因爲它返回一個純字符串。那麼爲什麼不保證字符串的工作? – Yevgeniy

回答

7

您可能正在使用早期版本的.Net Framework中的System.Net.NetworkCredential。 .Net 4.0中引入了接受SecureString的構造函數重載。如果您將SecureString傳遞給接受字符串的構造函數,powershell會將SecureString轉換爲一個字符串,該字符串呈現字符串「System.Security.SecureString」的值。你可以測試幾件事:

  1. 調用構造函數,然後查看它的密碼屬性,看看它的值是什麼。如果我的假設是正確的,它將是「System.Security.SecureString」。

  2. 看看哪個版本的。.NET框架使用的是:

    $ PSVersionTable.CLRVersion

  3. 查詢對象,看看有什麼構造函數有:

    一個。從Jeffrey Snover複製並粘貼function

    b。調用函數:

    GET-構造system.net.networkcredential

正如你可以從下面的輸出(我使用.NET 2.0)看 - 有沒有超載,接受一個SecureString的:

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

感謝您的回答!我確實在這個環境中運行.NET2。 – Yevgeniy

相關問題