Como posso inserir uma senha usando Perl e substituir os caracteres com '*'?
Pergunta
Eu tenho um script Perl que requer que o usuário digite uma senha. Como posso echo apenas '*' no lugar do personagem que o usuário digita, como eles digitá-lo?
Estou usando o Windows XP / Vista.
Solução
Você pode jogar com Term :: ReadKey. Aqui está um exemplo muito simples, com um pouco de detecção para backspace e tecla delete. Eu testei-o em Mac OS X 10.5, mas de acordo com a ReadKey Manual lo deve funcionar no Windows. A manual do indica que sob o Windows usando non-blocking lê (ReadKey(-1)
) irá falhar. É por isso que estou usando ReadKey (0), que é basicamente getc
(mais sobre getc na libc manual do ).
#!/usr/bin/perl
use strict;
use warnings;
use Term::ReadKey;
my $key = 0;
my $password = "";
print "\nPlease input your password: ";
# Start reading the keys
ReadMode(4); #Disable the control keys
while(ord($key = ReadKey(0)) != 10)
# This will continue until the Enter key is pressed (decimal value of 10)
{
# For all value of ord($key) see http://www.asciitable.com/
if(ord($key) == 127 || ord($key) == 8) {
# DEL/Backspace was pressed
#1. Remove the last char from the password
chop($password);
#2 move the cursor back by one, print a blank character, move the cursor back by one
print "\b \b";
} elsif(ord($key) < 32) {
# Do nothing with these control characters
} else {
$password = $password.$key;
print "*(".ord($key).")";
}
}
ReadMode(0); #Reset the terminal once we are done
print "\n\nYour super secret password is: $password\n";
Outras dicas
No passado, eu usei IO :: Prompt para isso.
use IO::Prompt;
my $password = prompt('Password:', -e => '*');
print "$password\n";
Se você não quiser usar quaisquer pacotes ... Apenas para UNIX
system('stty','-echo');
chop($password=<STDIN>);
system('stty','echo');
Você deve dar uma olhada em cada Term :: ReadKey ou Win32 :: Console . Você pode usar esses módulos para ler os cursos chaves individuais e emitem '*' ou whathever.
Com base no programa de Pierr-Luc, acabou de adicionar algum controle sobre as barras invertidas. Com isso, você não pode manter pressionando barra invertida para sempre:
sub passwordDisplay() {
my $password = "";
# Start reading the keys
ReadMode(4); #Disable the control keys
my $count = 0;
while(ord($key = ReadKey(0)) != 10) {
# This will continue until the Enter key is pressed (decimal value of 10)
# For all value of ord($key) see http://www.asciitable.com/
if(ord($key) == 127 || ord($key) == 8) {
# DEL/Backspace was pressed
if ($count > 0) {
$count--;
#1. Remove the last char from the password
chop($password);
#2 move the cursor back by one, print a blank character, move the cursor back by one
print "\b \b";
}
}
elsif(ord($key) >= 32) {
$count++;
$password = $password.$key;
print "*";
}
}
ReadMode(0); #Reset the terminal once we are done
return $password;
}
usando o programa de Pierr-Luc
# Start reading the keys
ReadMode(4); #Disable the control keys
while(ord($key = ReadKey(0)) != '13' )
# This will continue until the Enter key is pressed (decimal value of 10)
{
# For all value of ord($key) see http://www.asciitable.com/
if(ord($key) == 127 || ord($key) == 8 && (length($password) > 0)) {
# DEL/Backspace was pressed
#1. Remove the last char from the password
chop($password);
#2 move the cursor back by one, print a blank character, move the cursor back by one
print "\b \b";
} elsif(ord($key) > 32) {
$password = $password.$key;
print "*";
}
}
ReadMode(0); #Reset the terminal once we are done
Você tentou armazenar a string (para que o programa ainda pode lê-lo) e descobrir o seu comprimento, em seguida, criar uma cadeia do mesmo comprimento, mas apenas usar '*'?