【问题标题】:Hide input on command line隐藏命令行输入
【发布时间】:2012-06-04 21:01:40
【问题描述】:

我知道 Git 和其他命令行界面能够隐藏用户的输入(对密码很有用)。有没有办法在Java中以编程方式做到这一点?我正在从用户那里获取密码输入,我希望他们的输入在该特定行上“隐藏”(但不是在所有行上)。这是我的代码(虽然我怀疑它会有所帮助......)

try (Scanner input = new Scanner(System.in)) {
  //I'm guessing it'd probably be some property you set on the scanner or System.in right here...
  System.out.print("Please input the password for " + name + ": ");
  password = input.nextLine();
}

【问题讨论】:

    标签: java command-line input user-input command-prompt


    【解决方案1】:

    试试java.io.Console.readPassword。不过,您必须至少运行 Java 6。

       /**
        * Reads a password or passphrase from the console with echoing disabled
        *
        * @throws IOError
        *         If an I/O error occurs.
        *
        * @return  A character array containing the password or passphrase read
        *          from the console, not including any line-termination characters,
        *          or <tt>null</tt> if an end of stream has been reached.
        */
        public char[] readPassword() {
            return readPassword("");
        }
    

    但请注意,此 doesn't work 带有 Eclipse 控制台。您必须从 true 控制台/shell/终端/提示符运行程序才能对其进行测试。

    【讨论】:

    • +1 让我知道它在 Eclipse 控制台中不起作用(虽然我使用 Netbeans,但显然它在任何一个中都不起作用)。
    • 在大多数使用 javaw 的 IDE 中不起作用。见stackoverflow.com/a/26473083/3696510
    • 即使我创建jar并在控制台中运行它也不起作用,纯命令提示符。我得到空指针。
    • 这是一个例子:final String passwd; final String message = "Enter password"; if( System.console() == null ) { final JPasswordField pf = new JPasswordField(); passwd = JOptionPane.showConfirmDialog( null, pf, message, JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE ) == JOptionPane.OK_OPTION ? new String( pf.getPassword() ) : ""; } else passwd = new String( System.console().readPassword( "%s&gt; ", message ) );
    • 可能有助于添加如何检索Console 实例:``System.console()`
    【解决方案2】:

    有:

    Console cons;
    char[] passwd;
    if ((cons = System.console()) != null &&
        (passwd = cons.readPassword("[%s]", "Password:")) != null) {
        ...
        java.util.Arrays.fill(passwd, ' ');
    }
    

    source

    但我认为这不适用于像 Eclipse 这样的 IDE,因为该程序是作为后台进程而不是带有控制台窗口的顶级进程运行的。

    另一种方法是在摇摆中使用JPasswordField 和随附的actionPerformed 方法:

    public void actionPerformed(ActionEvent e) {
        ...
        char [] p = pwdField.getPassword();
    }
    

    source

    【讨论】:

      【解决方案3】:

      可以。这称为命令行输入屏蔽。您可以轻松实现这一点。

      您可以使用单独的线程在输入时删除回显的字符,并用星号替换它们。这是使用如下所示的 EraserThread 类完成的

      import java.io.*;
      
      class EraserThread implements Runnable {
         private boolean stop;
      
         /**
          *@param The prompt displayed to the user
          */
         public EraserThread(String prompt) {
             System.out.print(prompt);
         }
      
         /**
          * Begin masking...display asterisks (*)
          */
         public void run () {
            stop = true;
            while (stop) {
               System.out.print("\010*");
           try {
              Thread.currentThread().sleep(1);
               } catch(InterruptedException ie) {
                  ie.printStackTrace();
               }
            }
         }
      
         /**
          * Instruct the thread to stop masking
          */
         public void stopMasking() {
            this.stop = false;
         }
      }
      

      使用这个线程

      public class PasswordField {
      
         /**
          *@param prompt The prompt to display to the user
          *@return The password as entered by the user
          */
         public static String readPassword (String prompt) {
            EraserThread et = new EraserThread(prompt);
            Thread mask = new Thread(et);
            mask.start();
      
            BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
            String password = "";
      
            try {
               password = in.readLine();
            } catch (IOException ioe) {
              ioe.printStackTrace();
            }
            // stop masking
            et.stopMasking();
            // return the password entered by the user
            return password;
         }
      }
      

      This Link详细讨论。

      【讨论】:

      • 我正在调查这个答案,我喜欢密码屏蔽。但请包括您认为有用的文章内容,作为一个好的答案。
      • 答案中的链接似乎不再起作用。这是一个实时链接。 cse.chalmers.se/edu/course/TDA602/Eraserlab/pwdmasking.html
      • 奇怪的是,在 JetBrains IntelliJ 环境中代码会失败,因为 EraserThread 的 BS-* print 表现为 println。诡异的。但如果我直接从命令行运行它,它就可以工作(需要对EraserThread System.out.print(prompt) 进行小幅调整)
      • PasswordAppwww.cse.chalmers.se 页面上的行为并不完全符合人们的预期。线程一开始,提示的最后一个字符就会被星号覆盖。当输入其他字符时,会添加更多星号,以便始终比用户键入的字符多一个星号。这可能是一个外观问题,但很烦人。此外,线程每毫秒擦除和写入最后一个星号:有没有办法让它等到输入字符?
      【解决方案4】:

      JLine 2 可能感兴趣。除了字符掩码,它还将提供命令行补全、编辑和历史功能。因此,它对于基于 CLI 的 Java 工具非常有用。

      屏蔽您的输入:

      String password = new jline.ConsoleReader().readLine(new Character('*'));
      

      【讨论】:

        【解决方案5】:

        Console 类有一个方法readPassword() 可能会解决您的问题。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-05-14
          • 1970-01-01
          • 2016-08-04
          • 1970-01-01
          • 2018-10-13
          • 1970-01-01
          • 1970-01-01
          • 2013-03-30
          相关资源
          最近更新 更多