How to hide password entry from terminal in ruby ​​script

I'm new to ruby. I need to get the password as input through the gets command.

How to hide the password entered in the terminal during the gets call

+61
ruby
Feb 26 '10 at 1:15
source share
6 answers

Best way from @ eclectic923 answer:

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

For 1.9.3 (and higher), this requires adding require 'io/console' to your code.

Original answer:

Ruby " Password " is another alternative.

+3
Feb 26 '10 at 1:19
source share

You can also use core 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. 

For 1.9.3 (and higher), this requires adding require 'io/console' to your code.

 require 'io/console' text = STDIN.noecho(&:gets) 
+166
Aug 01 '12 at 18:29
source share

There is a library called highline that works as follows:

 require 'rubygems' require 'highline/import' password = ask("Enter password: ") { |q| q.echo = false } # do stuff with password 
+29
Feb 26 '10 at 1:18
source share

As others mention, you can use IO#noecho for Ruby> = 1.9. If you want to support 1.8, you can run the read command of the built-in 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 

Now getting a password is as simple as:

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



Note. . In an implementation using read above, you will run into a problem if you (or some other get_password client) pass through special shell characters at the prompt (for example, $ / " / ' / etc.). Ideally, you should Avoid the prompt line before passing it to the shell Unfortunately, Shellwords not available in Ruby 1.8. Fortunately, it is easy to back up the corresponding bits (in particular shellescape ), and you can do this small modification:

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



I mentioned a couple of problems using read -s -p in the comment below:

Well, case 1.8 is a bit dumb; this does not allow the backslash unless you press the backslash twice: "The backslash character` \ 'can be used to remove any special value for the next read character and to continue the line. " Also: "The characters in the value of the IFS variable are used to split the string into words." This should probably be good for most small scripts, but you probably want something more robust for larger applications.

We can fix some of these problems by folding our sleeves and doing this with stty(1) . An outline of what we need to do:

  • Save current terminal settings
  • Echo rotation
  • Print the invitation and get user input
  • Restore terminal settings

We must also take care of restoring terminal settings when interrupted by signals and / or exceptions. The following code will properly process job control signals (SIGINT / SIGTSTP / SIGCONT) while maintaining all the good effects with any signal handlers present:

 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 
+16
Mar 28 '13 at 14:54
source share

For ruby ​​version 1.8 (or Ruby <1.9), I used the read shell specified in @Charles.

By placing a code that is sufficient to request a username and password, where the username will be displayed on the screen while entering the password, the password will be entered into silent mode.

  userid = `read -p "User Name: " uid; echo $uid`.chomp passwd = `read -s -p "Password: " password; echo $password`.chomp 
+4
Aug 05 '14 at 22:02
source share

Starting with Ruby version 2.3.0, you can use the IO # getpass input method as follows: STDIN.getpass("Password:")

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

+3
Sep 26 '16 at 13:33
source share



All Articles