Program Tip

Ruby 스크립트에서 터미널에서 비밀번호 입력을 숨기는 방법

programtip 2020. 10. 22. 22:22
반응형

Ruby 스크립트에서 터미널에서 비밀번호 입력을 숨기는 방법


나는 루비를 처음 사용합니다. gets명령을 통해 비밀번호를 입력 받아야합니다 .

gets통화 중 단말기에 입력 한 비밀번호를 숨기는 방법


@ eclectic923의 답변에서 가장 좋은 방법 :

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

1.9.3 (이상)의 경우 require 'io/console'코드에 추가 해야합니다.

원래 답변 :

Ruby " Password "는 또 다른 대안입니다.


코어 루비를 사용할 수도 있습니다.

$ 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#noechoRuby> = 1.9에 사용할 수 있습니다 . 1.8에 대한 지원을 원하면 read내장 셸 기능 을 사용할 수 있습니다 .

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)를 전달 하면 문제가 발생합니다 . 이상적으로는 프롬프트 문자열을 쉘로 전달하기 전에 이스케이프해야합니다. 불행히도 ShellwordsRuby 1.8에서는 사용할 수 없습니다. 다행히도 관련 비트를 직접 백 포트하는 것은 쉽습니다 (특히 shellescape). 이를 통해 다음과 같이 약간의 수정을 할 수 있습니다.

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

read -s -p아래 댓글에서 의 사용과 관련된 몇 가지 문제를 언급했습니다 .

Well, the 1.8 case is a little janky; it doesn't allow for backslashes, unless you hit backslash twice: "The backslash character `\' may be used to remove any special meaning for the next character read and for line continuation." Also: "The characters in the value of the IFS variable are used to split the line into words. " This should probably be fine for most little scripts, but you'd probably want something more robust for larger applications.

We can fix some of those problems by rolling up our sleeves and doing this the hard with stty(1). An outline of what we need to do:

  • Store the current terminal settings
  • Turn of echoing
  • Print the prompt & get user input
  • Restore the terminal settings

We must also take care to restore the terminal settings when interrupted by signals and/or exceptions. The following code will properly handle job control signals (SIGINT/SIGTSTP/SIGCONT) while still playing nicely with any present signal handlers:

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

Starting from Ruby version 2.3.0 you can use the IO#getpass method like this:

require 'io/console'
password = STDIN.getpass("Password:")

See the getpass method in the Standard Library Documentation.


For ruby version 1.8 (or Ruby < 1.9) I used read shell builtin as mentioned by @Charles.

Putting the code thats just enough to prompt for user name & password, where user name will be echoed to screen while typing in however password typed in would be silent.

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

참고URL : https://stackoverflow.com/questions/2338889/how-to-hide-password-input-from-terminal-in-ruby-script

반응형