【问题标题】:Using PowerShell credentials without being prompted for a password在不提示输入密码的情况下使用 PowerShell 凭据
【发布时间】:2011-09-08 12:56:48
【问题描述】:

我想重新启动属于某个域的远程计算机。我有一个管理员帐户,但我不知道如何在 powershell 中使用它。

我知道有一个 Restart-Computer cmdlet,我可以传递凭据,但如果我的域是 mydomain,我的用户名是 myuser,我的密码是 mypassword,使用它的正确语法是什么?

我需要安排重新启动,这样我就不必输入密码了。

【问题讨论】:

  • 你应该阅读这个link
  • get-credential domain01\admin01 是什么意思?下一个命令是 restart-computer -computername $s -force -throttlelimit 10 -credential $c。这是否意味着get-credential无需询问即可检索密码?

标签: powershell powershell-remoting


【解决方案1】:

Get-Credential 的问题是它总是提示输入密码。但是有一种方法可以解决这个问题,但它涉及将密码作为安全字符串存储在文件系统上。

以下文章解释了它的工作原理:

Using PSCredentials without a prompt

总之,您创建一个文件来存储您的密码(作为加密字符串)。以下行将提示输入密码,然后将其作为加密字符串存储在 c:\mysecurestring.txt 中。您只需执行一次:

read-host -assecurestring | convertfrom-securestring | out-file C:\mysecurestring.txt

无论您在 PowerShell 命令的何处看到 -Credential 参数,都意味着您可以传递 PSCredential。所以在你的情况下:

$username = "domain01\admin01"
$password = Get-Content 'C:\mysecurestring.txt' | ConvertTo-SecureString
$cred = new-object -typename System.Management.Automation.PSCredential `
         -argumentlist $username, $password

$serverNameOrIp = "192.168.1.1"
Restart-Computer -ComputerName $serverNameOrIp `
                 -Authentication default `
                 -Credential $cred
                 <any other parameters relevant to you>

您可能需要不同的-Authentication 开关值,因为我不了解您的环境。

【讨论】:

  • 你也可以ConvertTo-SecureString "password" -AsPlainText -Force.
  • 只是为了说清楚,$password = ConvertTo-SecureString "password" -AsPlainText -Force
  • -Credential [username] 对我来说在 Read-Host 参数中是必需的,否则 powershell 就会挂起。将 -Credential 传递给 read-host 后,您将直接在 powershell 控制台中收到提示,并且密码已正确存储。谢谢!
  • 当我在 powershell 中使用 Send-MailMessage 功能时,我试图弄清楚如何让它工作。我想存储我的电子邮件用户的凭据并通过,这样我就不必继续输入它了。知道该怎么做吗?
  • @user3681591 - 我建议提出一个新问题,而不是在 cmets 中这样做。谢谢。
【解决方案2】:

还有另一种方法,但是...

如果您不希望脚本文件中包含您的密码,请不要这样做 (在脚本中存储密码不是一个好主意,但我们中的一些人只是想知道如何。)

好的,这是警告,这是代码:

$username = "John Doe"
$password = "ABCDEF"
$secstr = New-Object -TypeName System.Security.SecureString
$password.ToCharArray() | ForEach-Object {$secstr.AppendChar($_)}
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $secstr

$cred 将拥有来自 John Doe 的凭据,密码为“ABCDEF”。

另一种方法是让密码准备好使用:

$password = convertto-securestring -String "notverysecretpassword" -AsPlainText -Force

【讨论】:

  • 谢谢。这很有帮助。在我的例子中,我正在创建一个自定义的 powershell cmdlet,它需要一个用户名和密码(作为secureString)。 cmdlet 在内部调用其他几个 cmdlet,有些只需要用户和密码,但其中一个需要凭据,因此我实际上不需要在脚本中硬编码密码。
  • 稍微简单一点:$password = convertto-securestring -String "notverysecretpassword" -AsPlainText -Force
  • 当我在 powershell 中使用 Send-MailMessage 功能时,我试图弄清楚如何让它工作。我想存储我的电子邮件用户的凭据并通过,这样我就不必继续输入它了。知道该怎么做吗?
  • @user3681591 那将是 Send-MailMessage -Credential $cred(如本文所示创建了 $cred)
  • @JeroenLandheer 我已经尝试过您的答案(感谢您的帮助!)但是它没有用。我的错误是:-Credential:术语“-Credential”未被识别为 cmdlet、函数、脚本文件或可运行程序的名称。
【解决方案3】:

关于存储凭据,我使用了两个函数(通常在从我的配置文件加载的模块中):

#=====================================================================
# Get-MyCredential
#=====================================================================
function Get-MyCredential
{
param(
$CredPath,
[switch]$Help
)
$HelpText = @"

    Get-MyCredential
    Usage:
    Get-MyCredential -CredPath `$CredPath

    If a credential is stored in $CredPath, it will be used.
    If no credential is found, Export-Credential will start and offer to
    Store a credential at the location specified.

"@
    if($Help -or (!($CredPath))){write-host $Helptext; Break}
    if (!(Test-Path -Path $CredPath -PathType Leaf)) {
        Export-Credential (Get-Credential) $CredPath
    }
    $cred = Import-Clixml $CredPath
    $cred.Password = $cred.Password | ConvertTo-SecureString
    $Credential = New-Object System.Management.Automation.PsCredential($cred.UserName, $cred.Password)
    Return $Credential
}

还有这个:

#=====================================================================
# Export-Credential
# Usage: Export-Credential $CredentialObject $FileToSaveTo
#=====================================================================
function Export-Credential($cred, $path) {
      $cred = $cred | Select-Object *
      $cred.password = $cred.Password | ConvertFrom-SecureString
      $cred | Export-Clixml $path
}

你可以这样使用它:

$Credentials = Get-MyCredential (join-path ($PsScriptRoot) Syncred.xml)

如果凭证文件不存在,系统会第一次提示您,此时它会将凭证存储在 XML 文件内的加密字符串中。第二次运行该行时,xml 文件就在那里,并且会自动打开。

【讨论】:

    【解决方案4】:

    我必须从需要不同凭据的远程服务器运行 SCOM 2012 功能。我通过将密码解密函数的输出作为输入传递给 ConvertTo-SecureString 来避免使用明文密码。为清楚起见,此处未显示。

    我喜欢强烈键入我的声明。 $strPass 的类型声明工作正常。

    [object] $objCred = $null
    [string] $strUser = 'domain\userID'
    [System.Security.SecureString] $strPass = '' 
    
    $strPass = ConvertTo-SecureString -String "password" -AsPlainText -Force
    $objCred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList ($strUser, $strPass)
    

    【讨论】:

      【解决方案5】:

      如果您正在安排重新启动,您可以通过以下两种方式来执行此操作。

      首先,您可以使用具有连接和重新启动另一台计算机所需权限的凭据在一台计算机上创建任务。这使得调度程序负责安全地存储凭证。重启命令(我是一个 Powershell 人,但这更干净。)是:

      SHUTDOWN /r /f /m \\ComputerName

      在本地计算机上创建计划任务以远程重启另一台计算机的命令行是:

      SCHTASKS /Create /TN "Reboot Server" /TR "shutdown.exe /r /f /m \\ComputerName" /SC ONCE /ST 00:00 /SD "12/24/2012" /RU "domain\username" /RP "password"

      我更喜欢第二种方式,您可以使用您当前的凭据创建一个计划任务,该任务使用远程计算机上的系统帐户运行。

      SCHTASKS /Create /TN "Reboot Server" /TR "shutdown.exe /r /f" /SC ONCE /ST 00:00 /SD "12/24/2012" /RU SYSTEM /S ComputerName

      这也可以通过 GUI 进行,只需输入 SYSTEM 作为用户名,将密码字段留空。

      【讨论】:

        【解决方案6】:

        我看到了一个使用 Import/Export-CLIXML 的示例。

        对于您要解决的问题,这些是我最喜欢的命令。最简单的使用方法是。

        $passwordPath = './password.txt'
        if (-not (test-path $passwordPath)) {
            $cred = Get-Credential -Username domain\username -message 'Please login.'
            Export-CliXML -InputObject $cred -Path $passwordPath
        }
        $cred = Import-CliXML -path $passwordPath
        

        因此,如果该文件在本地不存在,它将提示输入凭据并存储它们。这将毫无问题地采用[pscredential] 对象并将凭据隐藏为安全字符串。

        最后像平常一样使用凭证。

        Restart-Computer -ComputerName ... -Credentail $cred
        

        安全注意事项

        Securely store credentials on disk

        阅读解决方案时,您可能首先对将密码存储在磁盘上持谨慎态度。 虽然小心在硬盘上乱扔垃圾是自然的(也是谨慎的) 敏感信息,Export-CliXml cmdlet 使用 Windows 标准数据保护 API。这确保只有您的用户帐户可以 正确解密其内容。同样,ConvertFrom-SecureString cmdlet 也 加密您提供的密码。

        编辑:只需重新阅读原始问题。只要您将[pscredential] 初始化到硬盘,上述操作就可以工作。也就是说,如果您将其放入脚本中并在创建该文件后运行该脚本,然后在无人参与的情况下运行该脚本将很简单。

        【讨论】:

        • 不错。你能纠正一个错字“Export-CliXML”吗,“xml”不见了。
        【解决方案7】:
        read-host -assecurestring | convertfrom-securestring | out-file C:\securestring.txt
        $pass = cat C:\securestring.txt | convertto-securestring
        $mycred = new-object -typename System.Management.Automation.PSCredential -argumentlist "test",$pass
        $mycred.GetNetworkCredential().Password
        

        以这种方式存储密码时要非常小心……它不如……安全。

        【讨论】:

          【解决方案8】:

          解决方案

          $userName = 'test-domain\test-login'
          $password = 'test-password'
          
          $pwdSecureString = ConvertTo-SecureString -Force -AsPlainText $password
          $credential = New-Object -TypeName System.Management.Automation.PSCredential `
              -ArgumentList $userName, $pwdSecureString
          

          用于构建机器
          在前面的代码中,将用户名和密码值替换为 build-machine 的秘密(“从日志中隐藏”)环境变量

          测试结果

          '# Results'
          $credential.GetNetworkCredential().Domain
          $credential.GetNetworkCredential().UserName
          $credential.GetNetworkCredential().Password
          

          你会看到

          # Results
          test-domain
          test-login
          test-password
          

          【讨论】:

            【解决方案9】:

            如果下面的代码可能对某人有所帮助。

            function Get-RemoteConnection()
            {
                //$serverIp can be passed as a parameter of the function.
                //I just make it static for testing. 
                $serverIp = '192.168.100.137'
                Enable-PSRemoting -Force
                Set-Item wsman:\localhost\client\trustedhosts $serverIp
                Restart-Service WinRM
                #Set credentials needed for remote installation
                $userName = "administrator"
                $password = ConvertTo-SecureString "2020core0515" -AsPlainText -Force
                $cred = New-Object System.Management.Automation.PSCredential -ArgumentList ($userName, $password)
                $session = New-PSSession -ComputerName $serverIp -Credential $cred
            
                $a = Invoke-Command -Session $session -ScriptBlock {  Get-WmiObject Win32_LogicalDisk -Filter "DriveType=3" | Select-Object DeviceID, @{label='UsedPercent'; expression={[Math]::Round((($_.size - $_.freespace) / $_.size) * 100, 2)}} }
            
                Write-Host $a
            
                return $session
            }
            
            function Delete-RemoteConnection($session)
            {
                Disconnect-PSSession $session | Out-Null
                Disable-WSManCredSSP -Role Client
            }
            

            【讨论】:

              【解决方案10】:

              这是我使用和为我工作的东西。

              $User="Domain\Username"
              $Password=[Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('VABlAHMAdABQAGEAcwBzAHcAbwByAGQA'))
              
              $SecurePassword = New-Object -TypeName System.Security.SecureString
              $Password.ToCharArray() | ForEach-Object {$SecurePassword.AppendChar($_)}
              
              $Credentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, $SecurePassword
              

              为了获得 VABlAHMAdABQAGEAcwBzAHcAbwByAGQA,我这样做:

              编码 $EString 表示加密字符串,$DString 表示解密字符串

              $EString = Read-Host "Type Text to Encode" -AsSecureString
              $BSTR=[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($EString)
              $DString=[System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
              $Encoded=[Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($DString))
              
              $Encoded # VABlAHMAdABQAGEAcwBzAHcAbwByAGQA
              $DString # TestPassword
              

              这样我就可以在脚本上输入我想要的任何密码,而不会太麻烦。

              【讨论】:

                【解决方案11】:

                您可以将其存储在凭证保险库中,而不是将加密密码存储在文本文件中。 在以下示例中,仅第一次提示用户输入密码,然后从凭证库中检索密码。

                # Load the Windows Runtime Class
                [Windows.Security.Credentials.PasswordVault,Windows.Security.Credentials,ContentType=WindowsRuntime]
                $Vault = New-Object Windows.Security.Credentials.PasswordVault
                
                $RESOURCE = "myresource"
                $USERNAME = "myuser"
                
                try {
                    $credentials = $Vault.Retrieve($RESOURCE,$USERNAME)
                    $pwd = $credentials.Password | ConvertTo-SecureString -Key (1..16)
                    }
                catch {
                    $pwd = Read-Host "please enter your password:" -AsSecureString
                    $Encrypted = ConvertFrom-SecureString -SecureString $pwd -Key (1..16)
                    $credentials = new-object -Type Windows.Security.Credentials.PasswordCredential -ArgumentList $RESOURCE,$USERNAME,$Encrypted
                    $Vault.Add($credentials)
                    }
                
                $cred = New-Object System.Management.Automation.PsCredential($USERNAME,$pwd)
                

                【讨论】:

                  【解决方案12】:

                  你为什么不尝试一些非常简单的事情呢?

                  将 psexec 与命令“shutdown /r /f /t 0”和来自 CMD 的 PC 列表一起使用。

                  【讨论】:

                  • 这是一个特殊情况。关键是在任何随机场景中都不会产生登录窗口。
                  猜你喜欢
                  • 2014-08-22
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-04-08
                  • 1970-01-01
                  • 2021-10-21
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多