2009-03-31 5 views

Respuesta

15

Puedes jugar con Term :: ReadKey. Aquí hay un ejemplo muy simple, con algo de detección de teclas de retroceso y eliminación. Lo probé en Mac OS X 10.5 pero según el ReadKey manual debería funcionar en Windows. El manual indica que en Windows, las lecturas sin bloqueo (ReadKey(-1)) fallarán. Es por eso que estoy usando ReadKey (0) que es básicamente getc (más en getc en el libc manual).

#!/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"; 
+3

Esto no funciona en Windows. Funciona bien hasta que llegue a presionar la tecla Intro, cuando tiene que presionarlo cuatro veces para que reaccione. Si usa ReadMode (2), funciona bien, pero no se repite hasta que toca return. No mostrar el * puede ser una alternativa aceptable –

+2

No funciona en Windows porque el valor de ascii decimal de la tecla Intro o Retorno es 13 (CR: retorno de carro). Una vez que reemplaza la línea while (ord ($ key = ReadKey (0))! = 10) con while (ord ($ key = ReadKey (0))! = 13), funciona mejor :) – Damien

+0

Probablemente también quiera para verificar "\ x03" (^ C); también, probablemente quiera emitir "\ b \ b" solo si la longitud ($ contraseña)> 0 o en función del valor de retorno de chop() (para evitar borrar el aviso si el usuario sigue retrocediendo) – vladr

-5

¿Ha intentado guardar la cadena (para que su programa todavía pueda leerla) y descubra su longitud, luego cree una cadena de la misma longitud, pero solo use '*'?

+0

Reemplazando el caracter con * mientras lo escriben. –

7

Debe echar un vistazo a Term::ReadKey o Win32::Console. Puede usar esos módulos para leer los trazos de teclas individuales y emitir '*' o lo que quiera.

25

En el pasado he usado IO::Prompt para esto.

use IO::Prompt; 
my $password = prompt('Password:', -e => '*'); 
print "$password\n"; 
+3

* [ESTADO ] (http://search.cpan.org/dist/IO-Prompt/lib/IO/Prompt.pm#STATUS): este módulo ya no se mantiene. Utilice el módulo IO :: Prompter en su lugar. * – reinierpost

17

Si no desea utilizar cualquier paquete ... Sólo para UNIX

system('stty','-echo'); 
chop($password=<STDIN>); 
system('stty','echo'); 
+0

'chomp' sería mejor que' chop' –

1

Basándose en el programa de Pierr-Luc, se agregó un cierto control sobre las barras invertidas. Con esto, no puede seguir presionando la barra invertida para siempre:

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; 
} 
+0

No hace falta contar $, la longitud ($ contraseña) hará. – vladr

Cuestiones relacionadas