在不提示输入密码的情况下使用 PowerShell 凭据

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

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

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

544167 次浏览

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

以下文章解释了这种方法的工作原理:

在没有提示符的情况下使用 PSCredentials

总之,创建一个文件来存储密码(以加密字符串的形式)。以下行将提示输入密码,然后将其作为加密字符串存储在 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开关值,因为我不知道您的环境。

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

#=====================================================================
# 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 文件内的加密字符串中。第二次运行该行时,xmlfile 已经存在并将自动打开。

还有一个办法,但是..。

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

这是警告,这是密码:

$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将拥有来自无名氏的凭证,密码为“ ABCDEF”。

Alternative means to get the password ready for use:

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

如果计划重新启动,有两种方法可以做到这一点。

首先,您可以使用凭据在一台机器上创建任务,凭据具有连接和重新启动另一台机器所需的权限。这使得调度程序负责安全地存储凭据。重新启动命令(我喜欢 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 作为用户名,密码字段为空。

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

用这种方式存储密码要非常小心... 它不像... 那么安全。

我必须从需要不同凭证的远程服务器运行 SCOM2012函数。我通过将密码解密函数的输出作为 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)

你为什么不试试很简单的方法呢?

使用 psexec 命令“ close/r/f/t 0”和来自 CMD 的 PC 列表。

我看到了一个使用 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

安全须知 :

安全地将凭据存储在磁盘上

在读取解决方案时,您可能首先要注意在磁盘上存储密码。 虽然这是自然的(和谨慎的) ,要小心地乱丢你的硬盘驱动器 敏感信息,Export-CliXml cmdlet 使用 Windows 标准数据保护 API。这确保只有您的用户帐户可以 同样,ConvertFrom-SecureStringcmdlet 也可以正确地解密其内容 加密您提供的密码。

编辑: 只要再读一遍原来的问题。只要将 [pscredential]初始化到硬盘上,以上方法就可以工作。也就是说,如果您将其放在脚本中,并在脚本创建该文件后运行该脚本,然后在无人参与的情况下运行该脚本将非常简单。

解决方案

$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

用于生成机器
在前面的代码中,用编译机器的环境变量(https://jenkins.io/doc/book/using/using-credit/”rel = “ nofollow noReferrer”> build-machine)的机密(“从日志中隐藏”)替换用户名和密码值

化验结果

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

到时候你就知道了

# Results
test-domain
test-login
test-password

以防下面的代码可能对某人有帮助。

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
}

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

$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 我这样做:

Encode $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

这样,我可以把任何密码,我想在脚本没有太多的麻烦。

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

# 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)