【发布时间】:2010-10-16 14:38:26
【问题描述】:
我有一个要求用户输入密码的 Perl 脚本。如何在用户键入时只回显“*”来代替用户键入的字符?
我使用的是 Windows XP/Vista。
【问题讨论】:
标签: perl terminal passwords echo
我有一个要求用户输入密码的 Perl 脚本。如何在用户键入时只回显“*”来代替用户键入的字符?
我使用的是 Windows XP/Vista。
【问题讨论】:
标签: perl terminal passwords echo
过去我为此使用过IO::Prompt。
use IO::Prompt;
my $password = prompt('Password:', -e => '*');
print "$password\n";
【讨论】:
如果您不想使用任何软件包...仅适用于 UNIX
system('stty','-echo');
chop($password=<STDIN>);
system('stty','echo');
【讨论】:
chomp 会比chop 更好
您可以使用 Term::ReadKey。这是一个非常简单的示例,对退格键和删除键进行了一些检测。我已经在 Mac OS X 10.5 上对其进行了测试,但根据 ReadKey manual 它应该可以在 Windows 下工作。 manual 表示在 Windows 下使用非阻塞读取 (ReadKey(-1)) 将失败。这就是我使用基本上是getc 的ReadKey(0) 的原因(更多关于getc 的内容请参见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";
【讨论】:
您应该查看Term::ReadKey 或Win32::Console。您可以使用这些模块来读取单个按键并发出“*”或其他任何内容。
【讨论】:
以 Pier-Luc 的程序为基础,只是在反斜杠上添加了一些控制。有了这个,你不能一直按反斜杠:
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;
}
【讨论】:
使用 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
【讨论】:
您是否尝试过存储字符串(以便您的程序仍然可以读取它)并找出它的长度,然后创建一个相同长度的字符串,但只使用 '*'?
【讨论】: