如何在ruby脚本中隐藏从terminalinput的密码

我是新来的ruby。 我需要通过gets命令接收密码作为input。

如何隐藏terminal中input的密码input,在gets通话期间

“ 密码 ”是另一种select。

也可以使用核心ruby。

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

对于1.9.3(及以上版本),这需要您在代码中添加require 'io/console'

 require 'io/console' text = STDIN.noecho(&:gets) 

有一个名为highline的库,其工作原理是这样的:

 require 'rubygems' require 'highline/import' password = ask("Enter password: ") { |q| q.echo = false } # do stuff with password 

正如其他人提到的,你可以使用IO#noecho Ruby> = 1.9。 如果你想要1.8的支持,你可以掏出内置的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 

现在获取密码就像下面这样简单:

 @password = get_password("Enter your password here: ") 

注意:在使用上面的read的实现中,如果你(或者某个其他的get_password客户端)在提示符(例如$ / " / ' / etc)中传递了特殊的shell字符,你会遇到麻烦。理想情况下,提示string,然后Shellwords shell。不幸的是,在Ruby 1.8中没有提供Shellwords 。幸运的是,你可以很容易地自己支持相关的位 (特别是shellescape ),因此可以稍作修改:

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

我在下面的评论中提到了使用read -s -p的一些问题:

那么1.8的情况有点不好, 它不允许反斜杠,除非你反斜杠两次:“反斜线字符'\'可能被用来删除下一个字符读取和连续行的任何特殊含义。 另外:“IFSvariables的值中的字符被用来将行分割成单词”。对于大多数小脚本来说,这应该是可以的,但是对于大型应用程序,您可能需要更强大的function。

我们可以通过卷起袖子来解决其中的一些问题,并用stty(1) 。 我们需要做什么的概要:

  • 存储当前的terminal设置
  • 回声的转动
  • 打印提示并获取用户input
  • 恢复terminal设置

当信号和/或exception中断时,我们还必须注意恢复terminal设置。 以下代码将正确处理作业控制信号(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 

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

把代码刚好足以提示input用户名和密码,input时用户名将回显到屏幕上,但input的密码将是无声的。

  userid = `read -p "User Name: " uid; echo $uid`.chomp passwd = `read -s -p "Password: " password; echo $password`.chomp 

从Ruby 2.3.0开始,你可以使用如下的IO#getpass方法: STDIN.getpass("Password:")

http://ruby-doc.org/stdlib-2.3.0/libdoc/io/console/rdoc/IO.html#method-i-getpass