Я новичок в рубине. Мне нужно получить пароль как вход через команду gets
.
Как скрыть ввод пароля, введенный в терминал, во время вызова gets
Я новичок в рубине. Мне нужно получить пароль как вход через команду gets
.
Как скрыть ввод пароля, введенный в терминал, во время вызова gets
require 'io/console'
password = STDIN.noecho(&:gets).chomp
Для 1.9.3 (и выше) для этого требуется добавить require 'io/console'
к вашему коду.
Ruby " Password" - еще одна альтернатива.
Можно также использовать 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.
Для 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, вы можете выполнить команду 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
) проходят по специальным символам оболочки в приглашении (например, $
/"
/'
/и т.д.). В идеале вам следует избегать строки приглашения, прежде чем передавать его в оболочку. К сожалению, Shellwords
недоступен в Ruby 1.8. К счастью, легко выполнить резервное копирование соответствующих битов (в частности shellescape
), При этом вы можете сделать эту небольшую модификацию:
def get_password(prompt="Password: ")
`read -s -p #{Shellwords.shellescape(prompt)} password; echo $password`.chomp
end
Я упомянул пару проблем с использованием read -s -p
в комментарии ниже:
Что ж, случай 1.8 немного болван; это не позволяет обратную косую черту, если вы не нажмете обратную косую черту дважды: "Символ обратной косой черты `\ 'может использоваться для удаления любого специального значения для следующего символа read и для продолжения строки". Также: "Символы в значении переменная 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
Для ruby версии 1.8 (или Ruby < 1.9) я использовал read оболочка, указанная в @Charles.
Поместив код, который достаточно для запроса имени пользователя и пароля, где имя пользователя будет отображаться на экране во время ввода пароля, пароль будет введен в тихий режим.
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