如何在ruby脚本中隐藏终端的密码输入

jsa*_*ath 73 ruby

我是红宝石的新手.我需要通过gets命令接收密码作为输入.

如何在gets通话期间隐藏在终端中输入的密码输入

ecl*_*923 180

人们也可以使用核心红宝石.

$ ri IO.noecho

 (from ruby core)
 ------------------------------------------------------------------------------
   io.noecho {|io| }
  ------------------------------------------------------------------------------

 Yields self with disabling echo back.

   STDIN.noecho(&:gets)

 will read and return a line without echo back.
Run Code Online (Sandbox Code Playgroud)

对于1.9.3(及更高版本),这需要您添加require 'io/console'代码.

require 'io/console'
text = STDIN.noecho(&:gets)
Run Code Online (Sandbox Code Playgroud)

  • 对于1.9.3,这需要您在代码中添加`require'io/console'.通常比任何宝石选择更好的方式. (21认同)
  • 不要忘记.chomp你的输入!pass = STDIN.noecho(&:gets).chomp (19认同)
  • 你如何让它在 Cygwin 中工作?`tmp.rb:2:in 'noecho':来自 tmp.rb:2:in <main> 的错误文件描述符 (Errno::EBADF)` (2认同)

Ott*_*ger 30

有一个名为highline的库,其工作方式如下:

require 'rubygems'
require 'highline/import'

password = ask("Enter password: ") { |q| q.echo = false }
# do stuff with password
Run Code Online (Sandbox Code Playgroud)


gho*_*g74 17

来自@ eclectic923答案的最佳方法:

require 'io/console'
password = STDIN.noecho(&:gets).chomp
Run Code Online (Sandbox Code Playgroud)

对于1.9.3(及更高版本),这需要您添加require 'io/console'代码.

原答案:

Ruby" 密码 "是另一种选择.

  • 这个答案应该弃用,以支持@ eclectic923核心ruby解决方案. (10认同)

Cha*_*les 16

正如其他人所提到的,你可以使用IO#noechoRuby> = 1.9.如果你想支持1.8,你可以使用read内置的shell函数:

begin
  require 'io/console'
rescue LoadError
end

if STDIN.respond_to?(:noecho)
  def get_password(prompt="Password: ")
    print prompt
    STDIN.noecho(&:gets).chomp
  end
else
  def get_password(prompt="Password: ")
    `read -s -p "#{prompt}" password; echo $password`.chomp
  end
end
Run Code Online (Sandbox Code Playgroud)

现在获取密码非常简单:

@password = get_password("Enter your password here: ")
Run Code Online (Sandbox Code Playgroud)

注意:在使用read上面的实现中,如果您(或其他一些客户端get_password)在提示符中传递特殊shell字符(例如$/ "/ '/ etc),则会遇到麻烦.理想情况下,您应该在将提示字符串传递给shell之前将其转义.不幸的是,ShellwordsRuby 1.8中没有.幸运的是,很容易自己(特别是)向后移动相关位shellescape.有了这个,你可以做一点修改:

  def get_password(prompt="Password: ")
    `read -s -p #{Shellwords.shellescape(prompt)} password; echo $password`.chomp
  end
Run Code Online (Sandbox Code Playgroud)

read -s -p在下面的评论中提到了几个问题:

嗯,1.8的情况有点笨拙; 它不允许使用反斜杠,除非你反击两次反斜杠:"反斜杠字符`\'可用于删除下一个字符读取和行继续的任何特殊含义." 另外:"IFS变量值中的字符用于将行拆分为单词."对于大多数小脚本来说这应该没什么问题,但是对于大型应用程序来说,你可能想要更强大的东西.

我们可以通过卷起袖子来解决其中的一些问题stty(1).我们需要做的概述:

  • 存储当前终端设置
  • 转身回响
  • 打印提示并获取用户输入
  • 恢复终端设置

当信号和/或异常中断时,我们还必须注意恢复终端设置.以下代码将正确处理作业控制信号(SIGINT/SIGTSTP/SIGCONT),同时仍然可以与任何当前的信号处理程序很好地协作:

require 'shellwords'
def get_password(prompt="Password: ")
  new_sigint = new_sigtstp = new_sigcont = nil
  old_sigint = old_sigtstp = old_sigcont = nil

  # save the current terminal configuration
  term = `stty -g`.chomp
  # turn of character echo
  `stty -echo`

  new_sigint = Proc.new do
    `stty #{term.shellescape}`
    trap("SIGINT",  old_sigint)
    Process.kill("SIGINT", Process.pid)
  end

  new_sigtstp = Proc.new do
    `stty #{term.shellescape}`
    trap("SIGCONT", new_sigcont)
    trap("SIGTSTP", old_sigtstp)
    Process.kill("SIGTSTP", Process.pid)
  end

  new_sigcont = Proc.new do
    `stty -echo`
    trap("SIGCONT", old_sigcont)
    trap("SIGTSTP", new_sigtstp)
    Process.kill("SIGCONT", Process.pid)
  end

  # set all signal handlers
  old_sigint  = trap("SIGINT",  new_sigint)  || "DEFAULT"
  old_sigtstp = trap("SIGTSTP", new_sigtstp) || "DEFAULT"
  old_sigcont = trap("SIGCONT", new_sigcont) || "DEFAULT"

  print prompt
  password = STDIN.gets.chomp
  puts

  password
ensure
  # restore term and handlers
  `stty #{term.shellescape}`

  trap("SIGINT",  old_sigint)
  trap("SIGTSTP", old_sigtstp)
  trap("SIGCONT", old_sigcont)
end
Run Code Online (Sandbox Code Playgroud)


Zor*_*vic 11

从Ruby版本2.3.0开始,您可以使用如下IO#getpass方法:

require 'io/console'
password = STDIN.getpass("Password:")
Run Code Online (Sandbox Code Playgroud)

请参阅标准库文档中的getpass方法.

  • 如何使用 getpass 回显 * 等特定字符? (2认同)

Ris*_*shi 5

对于ruby版本1.8(或Ruby <1.9),我使用了@Charles提到的内置读取 shell。

只需输入足以提示用户名和密码的代码即可,在键入用户名时会在屏幕上回显用户名,但键入的密码将保持静音。

 userid = `read -p "User Name: " uid; echo $uid`.chomp
 passwd = `read -s -p "Password: " password; echo $password`.chomp
Run Code Online (Sandbox Code Playgroud)