Hide input on command line

JavaCommand LineInputUser InputCommand Prompt

Java Problem Overview


I know that command line interfaces like Git and others are able to hide input from a user (useful for passwords). Is there a way to programmtically do this in Java? I'm taking password input from a user and I would like their input to be "hidden" on that particular line (but not on all of them). Here's my code for it (though I doubt it would be helpful...)

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 Solutions


Solution 1 - Java

Try java.io.Console.readPassword. You'll have to be running at least Java 6 though.

   /**
    * 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("");
    }

Beware though, this doesn't work with the Eclipse console. You'll have to run the program from a true console/shell/terminal/prompt to be able to test it.

Solution 2 - Java

Yes can be done. This is called Command-Line Input Masking. You can implement this easily.

You can uses a separate thread to erase the echoed characters as they are being entered, and replaces them with asterisks. This is done using the EraserThread class shown below

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

With using this thread

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 discuss in details.

Solution 3 - Java

JLine 2 may be of interest. As well as character masking, it'll provide command-line completion, editing and history facilities. Consequently it's very useful for a CLI-based Java tool.

To mask your input:

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

Solution 4 - Java

There is :

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

source

but I don't think this works with an IDE like Eclipse because the program is run as a background process rather than a top level process with a console window.

Another approach is to use the JPasswordField in swing with the accompanying actionPerformed method:

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

source

Solution 5 - Java

The class Console has a method readPassword() that might solve your problem.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionkentcdoddsView Question on Stackoverflow
Solution 1 - JavaadarshrView Answer on Stackoverflow
Solution 2 - JavaVijay Shanker DubeyView Answer on Stackoverflow
Solution 3 - JavaBrian AgnewView Answer on Stackoverflow
Solution 4 - JavaDhruv GairolaView Answer on Stackoverflow
Solution 5 - JavarlindenView Answer on Stackoverflow