【问题标题】:How can Perl prompt for a password without showing it in the terminal?Perl 如何在不显示终端的情况下提示输入密码?
【发布时间】:2016-09-30 22:56:03
【问题描述】:

如何在终端不显示密码的情况下提示终端用户输入密码? How can I enter a password using Perl and replace the characters with '*'? 有一个类似的问题,但答案似乎已过时或损坏。

我一直在寻找这个问题的答案,但对结果后面几页中的问题不满意,这些问题的答案与其他问题无关。

另外,perlfaq8 有一个不完整的示例(哦,谁曾经维护过它;)。

 use Term::ReadKey;
 ReadMode('noecho');
 my $password = ReadLine(0);

当您在不重置终端的情况下执行此操作时,没有其他任何回声!糟糕!

我也在寻找更新的答案或模块,我们可以提供给想要这样做的人。

【问题讨论】:

  • 过去几年这里有什么变化吗? - 对我来说(截至 09/2020)这适用于 LWP::UserAgent:print "password please: "; ReadMode('noecho'); my $pass=ReadLine(0); chomp($pass); $request->authorization_basic('username', $pass);
  • LWP 与它没有任何关系。否则你有相同的代码。
  • 正确。我的意思是,我在 LWP 的上下文中使用了 perlfaq8 中的那些行(这可能是无用的信息)——在这种情况下它工作得非常好。没问题,无需重置终端。 (也许你在 4 年前看到的问题已经解决了?不知道)

标签: perl terminal passwords


【解决方案1】:

要使用Term::ReadKey,这样可以:

sub prompt_for_password {
    require Term::ReadKey;

    # Tell the terminal not to show the typed chars
    Term::ReadKey::ReadMode('noecho');

    print "Type in your secret password: ";
    my $password = Term::ReadKey::ReadLine(0);

    # Rest the terminal to what it was previously doing
    Term::ReadKey::ReadMode('restore');

    # The one you typed didn't echo!
    print "\n";

    # get rid of that pesky line ending (and works on Windows)
    $password =~ s/\R\z//;

    # say "Password was <$password>"; # check what you are doing :)

    return $password;
}

【讨论】:

  • 这可以通过决定修剪前导或尾随空格以及如何从末尾删除某些内容来改进。在 Windows 上 chomp 可能不会做正确的事情。
  • 通过上面的例程,chomp 确实在 Windows 上做正确的事。有关IO::Prompter 的问题,请参阅RT #118255
  • 如果用户在密码提示下按 Ctrl-C,此解决方案不会将终端恢复到之前的 (echo) 状态。为了解决这个问题,必须设置一个$SIG{INT} = sub { ... }; 处理程序。
  • 这是一个社区维基,所以你可以编辑答案:)
【解决方案2】:

你也可以使用IO::Prompter:

$ perl -MIO::Prompter -wE '$pass = prompt("Password: ", -echo =&gt; "*"); $pass =~ s/\R\z//; say $pass'

仅仅询问密码可能有点过头了,但如果您还需要引出其他类型的用户输入,这很有用。请注意,您确实需要Term::ReadKey 才能使密码屏蔽功能起作用。不幸的是,该模块不会在构建时警告您。如果上面的单行生成警告,您将知道您处于这种情况:

Warning: next input will be in plaintext

prompt() 子例程使用 -echo 标志调用,但 Term::ReadKey 模块无法实现此功能。输入将照常进行,但发出此警告是为了确保用户不会输入机密信息,期望它保持隐藏状态,但事实并非如此。

该警告消息如何对应于解释中给出的含义我无法理解,但是,哦,好吧。

请注意,在 Windows 上,模块会在输入字符串的末尾留下 CRchomp 不会删除(因为它正在寻找 CRLF 序列)。这就是我在上面的示例中使用\R 的原因。见RT #118255

【讨论】:

    【解决方案3】:

    Term::ReadPassword::Win32 在 Win32 和 Unix 上都可以工作(尽管它的名字暗示了其他方式)。在 Unix 上,它使用 Term::ReadPassword

    use strict;
    use warnings;
    use Term::ReadPassword::Win32 qw(read_password);
    my $input = read_password("Password: ");
    say $input;
    

    不幸的是,我找不到适用于标准 Perl 模块(即无需安装)的简短解决方案。如果您无法从 CPAN 安装,您可能需要从上面的模块中复制粘贴代码。

    【讨论】:

      【解决方案4】:

      网上有很多包含system("stty -echo") 的建议,但这在 Win32 上不起作用(仅适用于 Unix),并且使用它的实际强大解决方案很快变得复杂(超过 30 行,存在可移植性问题):1 . 处理Ctrl-C 是一团糟(需要$SIG{INT} = ... 或更多stty 标志),以及2. 获取TTY 设备文件句柄并将其传递给stty 很棘手(使用shell 重定向或一些 Perl open(...) 魔术),以防 stdin、stdout 或 stderr 被重定向。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-08-15
        • 2011-09-08
        • 2012-04-21
        • 2012-04-02
        • 2015-04-08
        • 1970-01-01
        • 2016-05-27
        相关资源
        最近更新 更多