为变量转义 Powershell 中的所有密码特殊字符

Escaping all password special characters in Powershell for Variable

我有以下场景,运行在 Powershell v5 上运行:

一个 Powershell 脚本从一个 API 调用中提取几位信息到一个批量 for-each 循环中的第 3 方系统,并将它们分配给变量。提取的信息包括密码(这样做是为了摆脱上述第 3 方系统并将其迁移到不允许您以纯文本形式检索密码的系统):

$userset = Invoke-WebRequest -Method Post -Uri "https://$Url/path/to/api.asmx" -Headers $Headers -Body $usercall

$xmluserset = [xml] $userset.Content

$userset2 = $xmluserset.Envelope.Body.UserSettingsResult.settingValues.string

$userpasstemp = $userset2[1].trimstart("password")
$userpass = $userpasstemp.trimstart("=")

然后在脚本的其他地方使用这些密码。

例如,它们被传递给不同的 API 并且需要采用 URL 兼容的格式,所以我 运行 这个:

$urlescapeduserpass = [uri]::EscapeDataString($userpass)

适用于脚本的该部分

问题是这些密码可以包含任何特殊字符: !"#$%&'()*+,-./:;<=>?@[]^_`{|}~

并且当我调用脚本的另一部分时,密码字符串中的特殊字符导致失败并退出脚本。使用调用命令时会发生这种情况:

& .\application.exe --option1 $option1 --user1 $user --password1 $userpass

或使用 invoke-expression 时

$command = "$path\application.exe  --option1 $option1 --user1 $user --password1  $userpass"
Invoke-Expression $command

我尝试使用 Regex,使用 -replace cmdlet:

$escapedpass = $userpass -replace ' !"#$%&()*+,-./:;<=>?@[\]^_`{|}~', '`$&'

但运气不好,我知道与 [uri]escapedatastring 类似,Regex 也有一个类似的字符串,但似乎没有 Powershell 的本地字符串。我确定有一个 [contenttype] 将具有本机函数来转义特殊字符或某种方式来实现最终结果。

让我们 create a Minimal, Reproducible Example with a round trip based on the answer from @mklement0 为此:
(也考虑到我刚刚在空格上发表的评论)

不幸的是,PowerShell 造成了额外的障碍,因为它需要对字符串进行单引号,否则它将解释其他字符以及美元符号 ($)。我在代码中放置了注释,您可能会忽略它。

Password.ps1

Param (
    [String]$Password
)
Write-Host $Password

密码检查:

$Input = @'
 !"'#$%&()*+,-./:;<=>?@[\]^_`{|}~
'@

Write-Host 'Input:' $Input
$Escape = $Input.Replace('"', '\"')
$Escape = $Escape.Replace("'", "''") # Only required for PowerShell
Write-Host 'Command:' PowerShell .\Password.ps1 "'$Escape'"
# Omit the inner single quotes if it doesn't concern PowerShell
# But note that your .\application.exe might have its own syntax
# to support spaces and special characters from the command line,
# like double quotes: """$Escape"""
$Output = & PowerShell .\Password.ps1 "'$Escape'"
Write-Host 'Output:' $Output
Write-Host 'Input and output are equal?' ($Input -eq $Output)

结果:

Input:  !"'#$%&()*+,-./:;<=>?@[\]^_`{|}~
Command: PowerShell .\Password.ps1 "' !\"''#$%&()*+,-./:;<=>?@[\]^_`{|}~'"
Output:  !"'#$%&()*+,-./:;<=>?@[\]^_`{|}~
Input and output are equal? True

因为 PowerShell 对传递给 外部程序 的参数中嵌入的 " 字符的处理被破坏了(从 PowerShell 7 开始) - 请参阅 - 您需要 手动 \-转义 " 个字符 嵌入到您的字符串中:

$escapedpass = $userpass -replace , '"', '\"'

在您的命令上下文中:

& .\application.exe --option1 $option1 --user1 $user --password1 ($userpass -replace , '"', '\"')