Hide input on command line
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();
}
Solution 1:
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:
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:
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:
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