I hit this eclipse bug, where System.console()
is not available for Java application launches. I have a small Java app that also requires a password to be entered that is only started from within the IDE. Is there any other way to safely read a password (meaning not displaying it on the console) from the console with only using JDK classes?
EDIT:
I know of System.in
, but that is displaying the inputed characters in the console and is therefore not safe.
EDIT2:
I also want to note that one can create a batch file under windows or a small bash script under linux/unix in the project. By openening this file in eclipse with the system default editor, it will be started in a new console window where System.console()
is available. This way you can start the application from within eclipse. but the project has to be built first, so that the binaries exist.
If System.console()
returns null
, that means that there is no usable console as far as Java is concerned.
You can't use System.in
because the chances are that it is not connected to a console.
Even if you could, there is no portable way to turn off echoing in Java.
You might be able to use Swing (or whatever) to pop up a window to ask for the password, but if the system is headless that won't work.
If you are prepared to do non-portable things, then (on Linux / UNIX) you could try opening "/dev/console" or "/dev/tty". And then you could use termios to put the tty driver into noecho mode. But you'll need to do at least some of this in native code.
Maybe instead of console try using dialog with JPasswordField
. Here is example from http://blogger.ziesemer.com/2007/03/java-password-dialog.html.
final JPasswordField jpf = new JPasswordField();
JOptionPane jop = new JOptionPane(jpf, JOptionPane.QUESTION_MESSAGE,
JOptionPane.OK_CANCEL_OPTION);
JDialog dialog = jop.createDialog("Password:");
dialog.addComponentListener(new ComponentAdapter() {
@Override
public void componentShown(ComponentEvent e) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
jpf.requestFocusInWindow();
}
});
}
});
dialog.setVisible(true);
int result = (Integer) jop.getValue();
dialog.dispose();
char[] password = null;
if (result == JOptionPane.OK_OPTION) {
password = jpf.getPassword();
}
if (password != null)
System.out.println("your password: " + new String(password));
I ran into the same issue. (Dear Eclipse Community: Is it so hard to fix that bug?)
As everyone else I need the IDE for dev/debug and standalone for running.
So I wrote this method:
private static String readPwd() throws IOException {
Console c=System.console();
if (c==null) { //IN ECLIPSE IDE
System.out.print("Password: ");
InputStream in=System.in;
int max=50;
byte[] b=new byte[max];
int l= in.read(b);
l--;//last character is \n
if (l>0) {
byte[] e=new byte[l];
System.arraycopy(b,0, e, 0, l);
return new String(e);
} else {
return null;
}
} else { //Outside Eclipse IDE
return new String(c.readPassword("Password: "));
}
}
Downside of this workaround is that in Eclipse you are going to see the password during the runtime of the program.
Similar to the answer given by @Pshemo, one could fall back to Swing:
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> ", message ) );