So verbergen Sie die Passworteingabe vom Terminal in Ruby Script


Antworten:


21

Beste Methode aus der Antwort von @ eclectic923:

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

Für 1.9.3 (und höher) müssen Sie require 'io/console'Ihren Code hinzufügen .

Ursprüngliche Antwort:

Ruby " Passwort " ist eine weitere Alternative.


Danke ... genau das habe ich gesucht
jsampath

10
Diese Antwort sollte zugunsten der @ eclectic923-Kern-Rubinlösung abgelehnt werden.
Notapatch

183

Man kann auch Kern Rubin verwenden.

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

Für 1.9.3 (und höher) müssen Sie require 'io/console'Ihren Code hinzufügen .

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

21
Für 1.9.3 müssen Sie require 'io/console'Ihren Code hinzufügen . Viel besser als jede Edelsteinoption normalerweise.
icco

1
Ich kann diese Antwort nicht genug +1. Beats, die jeden Tag zusätzliche Edelsteine ​​enthalten müssen!
Mydoghaswürmer

19
Vergessen Sie nicht, Ihre Eingabe zu ändern! pass = STDIN.noecho (&: bekommt) .chomp
avguchenko

1
Wie bringt man das in Cygwin zum Laufen? tmp.rb:2:in 'noecho': Bad file descriptor (Errno::EBADF) from tmp.rb:2:in <main>
Chloe

30

Es gibt eine Bibliothek namens Highline, die so funktioniert:

require 'rubygems'
require 'highline/import'

password = ask("Enter password: ") { |q| q.echo = false }
# do stuff with password

16

Wie die anderen erwähnen, können Sie IO#noechofür Ruby> = 1.9 verwenden. Wenn Sie Unterstützung für 1.8 readwünschen , können Sie die integrierte Shell-Funktion verwenden:

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

Jetzt ist es so einfach, ein Passwort zu erhalten wie:

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

Hinweis: Bei der oben verwendeten Implementierung readtreten Probleme auf, wenn Sie (oder ein anderer Client von get_password) spezielle Shell-Zeichen in der Eingabeaufforderung (z. B. $/ "/ '/ etc) weitergeben. Im Idealfall sollten Sie die Eingabeaufforderungszeichenfolge maskieren, bevor Sie sie an die Shell weitergeben. Ist Shellwordsin Ruby 1.8 leider nicht verfügbar. Glücklicherweise ist es einfach, die relevanten Bits selbst (speziell shellescape) zurück zu portieren . Damit können Sie diese geringfügige Änderung vornehmen:

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

Ich erwähnte ein paar Probleme mit der Verwendung von read -s -pin einem Kommentar unten:

Nun, der 1.8-Fall ist ein bisschen ruckelig; Backslashes sind nicht zulässig, es sei denn, Sie drücken zweimal Backslash: "Das Backslash-Zeichen" \ "kann verwendet werden, um spezielle Bedeutungen für das nächste gelesene Zeichen und für die Fortsetzung der Zeile zu entfernen." Außerdem: "Die Zeichen im Wert der IFS-Variablen werden verwendet, um die Zeile in Wörter aufzuteilen." Dies sollte wahrscheinlich für die meisten kleinen Skripte in Ordnung sein, aber für größere Anwendungen möchten Sie wahrscheinlich etwas Robusteres.

Wir können einige dieser Probleme beheben, indem wir die Ärmel hochkrempeln und dies mit aller Kraft tun stty(1). Ein Überblick darüber, was wir tun müssen:

  • Speichern Sie die aktuellen Terminaleinstellungen
  • Schalten Sie das Echo aus
  • Drucken Sie die Eingabeaufforderung aus und erhalten Sie Benutzereingaben
  • Stellen Sie die Terminaleinstellungen wieder her

Wir müssen auch darauf achten, die Terminaleinstellungen wiederherzustellen, wenn sie durch Signale und / oder Ausnahmen unterbrochen werden. Der folgende Code verarbeitet Jobsteuerungssignale (SIGINT / SIGTSTP / SIGCONT) ordnungsgemäß, während er weiterhin mit allen vorhandenen Signalhandlern spielt:

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

Nun, der 1.8-Fall ist ein bisschen ruckelig; Backslashes sind nur zulässig, wenn Sie zweimal auf Backslash klicken: "Das Backslash-Zeichen" \ "kann verwendet werden, um spezielle Bedeutungen für das nächste gelesene Zeichen und für die Fortsetzung der Zeile zu entfernen." Außerdem: "Die Zeichen im Wert der IFS-Variablen werden verwendet, um die Zeile in Wörter aufzuteilen." Dies sollte wahrscheinlich für die meisten kleinen Skripte in Ordnung sein, aber Sie möchten wahrscheinlich etwas Robusteres für größere Anwendungen.
Charles

16

Ab Ruby Version 2.3.0 können Sie die folgende IO#getpassMethode verwenden:

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

Siehe die getpass- Methode in der Standardbibliotheksdokumentation.


Wie kann man mit getpass ein bestimmtes Zeichen wie * wiedergeben?
João Ramires

5

Für Ruby Version 1.8 (oder Ruby <1.9) habe ich die von @Charles erwähnte Read Shell verwendet.

Wenn Sie den Code eingeben, der gerade ausreicht, um zur Eingabe von Benutzername und Kennwort aufzufordern, wobei der Benutzername während der Eingabe auf dem Bildschirm angezeigt wird, das eingegebene Kennwort jedoch stumm bleibt.

 userid = `read -p "User Name: " uid; echo $uid`.chomp
 passwd = `read -s -p "Password: " password; echo $password`.chomp
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.