如何让ReadLineAsSecureString()接受管道输入?

问题描述 投票:1回答:1

当我使用cmd和管道到使用powershell读取输入的ReadLine()时,它按预期接受管道输入:

C:\Users\ohnob>ECHO hi|powershell -Command "write-host $host.UI.ReadLine()"
hi
hi

但是,当我使用cmd和管道使用powershell ReadLineAsSecureString()时,它会挂起,直到我输入到终端:

C:\Users\ohnob>ECHO hi|powershell -Command "write-host $host.UI.ReadLineAsSecureString()"

当会话是交互式的时候,我需要读作一个安全的字符串(使用星号)。但是当有输入管道时我需要读取管道输入。我如何在powershell中实现这一目标?我希望我能够以某种方式检测stdin是否是管道然后有条件地使用ReadLine()而不是ReadLineAsSexcureString(),但我不知道如何在powershell中获得标准输入的句柄 - 我只能访问此PSHostUserInterface对象。

编辑:澄清一下,当我使用ReadLineAsSecureString()ReadLine()时,我希望它从输入中读取一行。这允许它被多次使用,并且用户可以为脚本提供多个值。我希望任何答案都是我使用的功能的替代品,除非我没有遇到的问题。谢谢!

windows powershell cmd
1个回答
1
投票

Jeroen Mostert在评论中提出了一些好处,特别是出于安全原因,$host.UI.ReadLineAsSecureString() / Read-Host -AsSecureString可能不接受管道输入[1]。

因此,您必须明确区分接收管道输入和不接收任何:

  • PowerShell通过自动$Input变量提供对从外部传输的stdin输入的访问。
  • $MyInvocation.ExpectingInput通常表示是否存在管道输入。

如果有管道输入,则将其第一行[2]传递给ConvertTo-SecureString; 如果没有,请致电Read-Host -AsSecureString

$secStr = if ($MyInvocation.ExpectingInput) {
    # Alternatively, use $firstLine = [console]::ReadLine() - thanks, @binki
    $firstLine = $($null = $Input.MoveNext(); $Input.Current)
    ConvertTo-SecureString -AsPlainText -Force $firstLine
  } else {
    Read-Host -AsSecureString -Prompt 'Enter secret'
  }

作为从cmd.exe调用的命令行,它也输出结果:

C:>echo hi| powershell -Command "$secStr = if ($MyInvocation.ExpectingInput) { $firstLine = $($null = $Input.MoveNext(); $Input.Current); ConvertTo-SecureString -AsPlainText -Force $firstLine } else { Read-Host -AsSecureString -Prompt 'Enter secret' }l$secStr"

但是请注意,通过设计将字符串安全打印为System.Security.SecureString,这就是你所能看到的。


[1]我猜测缺乏这方面的文件。将明文字符串管道化为Read-Host -AsSecureString肯定有更大的不安全潜力:被管道传输的纯文本字符串可能会在某处保持,至少假设,如果你使用像MyCustomEcho.exe secret | ...这样的东西,过程'命令行将反映秘密信息。 无论哪种方式,将纯文本传递给ConvertTo-SecureString -AsPlainText始终是一个选项,其中传递-Force的额外需求也表明PowerShell考虑使用未以交互方式键入的纯文本输入。

[2]自动$Input变量是一个枚举器(类型),它根据需要枚举来自stdin的行。不支持$Input[0]等索引访问;相反,你必须使用.MoveFirst()来启动枚举,然后访问.Current属性以获得第一行。这样,剩余的元素不被消耗,后来使用$Input产生剩余的行。 围绕$(...)$null = $Input.MoveNext(); $Input.Current的唯一原因是,为了概念清晰,这两个语句可以包含在返回第一行的单个语句中;首先使用$null = $Input.MoveNext()$firstLine = $Input.Current也很好。

© www.soinside.com 2019 - 2024. All rights reserved.