【问题标题】:How can I enter a password using Perl and replace the characters with '*'?如何使用 Perl 输入密码并将字符替换为“*”?
【发布时间】:2010-10-16 14:38:26
【问题描述】:

我有一个要求用户输入密码的 Perl 脚本。如何在用户键入时只回显“*”来代替用户键入的字符?

我使用的是 Windows XP/Vista。

【问题讨论】:

    标签: perl terminal passwords echo


    【解决方案1】:

    过去我为此使用过IO::Prompt

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

    【讨论】:

    • STATUS:该模块不再维护。请改用 IO::Prompter 模块。
    【解决方案2】:

    如果您不想使用任何软件包...仅适用于 UNIX

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

    【讨论】:

    • chomp 会比chop 更好
    【解决方案3】:

    您可以使用 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";   
    

    【讨论】:

    • 这在 Windows 下不起作用。在您按下回车键之前,它工作正常,当您必须按四次才能做出反应时。如果您使用 ReadMode(2),那么它可以正常工作,但在您按回车之前不会回显。不显示 * 可能是可接受的替代方案
    • 它在 Windows 上不起作用,因为 Enter 或 Return 键的十进制 ascii 值为 13(CR:回车)。将 while(ord($key = ReadKey(0)) != 10) 替换为 while(ord($key = ReadKey(0)) != 13) 后,效果会更好:)
    • 您可能还想检查 "\x03" (^C);此外,您可能只想在 length($password) > 0 或基于chop() 的返回值时发出“\b \b”(以避免在用户继续回溯时删除提示)
    • 1. Damien 是对的:在为关键测试添加 13 时,在 Windows 下就像一个魅力。 2. Vladr:在Windows下不需要测试^C,也不需要测试^Break。 ReadKey 似乎不受这些中断的影响。用长度(密码)实现了你关于“\ b ...”的想法。完美的。 3. 所有其他模块 IOPrompt[er] 和类似的模块在 Windows(7/64 和 10/64)下都是不行的。这个解决方案就是一个。
    【解决方案4】:

    您应该查看Term::ReadKeyWin32::Console。您可以使用这些模块来读取单个按键并发出“*”或其他任何内容。

    【讨论】:

      【解决方案5】:

      以 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;
      }
      

      【讨论】:

      • 不需要$count,length($password) 就可以了。
      【解决方案6】:

      使用 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
      

      【讨论】:

        【解决方案7】:

        您是否尝试过存储字符串(以便您的程序仍然可以读取它)并找出它的长度,然后创建一个相同长度的字符串,但只使用 '*'?

        【讨论】:

        • 在键入时将字符替换为 *。
        猜你喜欢
        • 2017-10-02
        • 2010-11-24
        • 1970-01-01
        • 1970-01-01
        • 2017-03-14
        • 1970-01-01
        • 2020-08-12
        • 2016-06-18
        • 2019-01-15
        相关资源
        最近更新 更多