问题
I'm writing a commandline program that prompts for a passwd and I don't want it to do local echo of the password characters. After some searches, I have stumbled upon System.console().readPassword(), which seems great, except when dealing with pipes in Unix. So, my example program (below) works fine when I invoke it as:
% java PasswdPrompt
but fails with Console == null when I invoke it as
% java PasswdPrompt | less
or
% java PasswdPrompt < inputfile
IMHO, this seems like a JVM issue, but I can't be the only one who has run into this problem so I have to imagine there are some easy solutions.
Any one?
Thanks in advance
import java.io.Console;
public class PasswdPrompt {
public static void main(String args[]) {
Console cons = System.console();
if (cons == null) {
System.err.println("Got null from System.console()!; exiting...");
System.exit(1);
}
char passwd[] = cons.readPassword("Password: ");
if (passwd == null) {
System.err.println("Got null from Console.readPassword()!; exiting...");
System.exit(1);
}
System.err.println("Successfully got passwd.");
}
}
回答1:
From the Java documentation page :
If System.console returns NULL, then Console operations are not permitted, either because the OS doesn't support them or because the program was launched in a noninteractive environment.
The problem is most likely because using a pipe falls out of "interactive" mode and using an input file uses that as System.in, thus no Console.
** UPDATE **
Here's a quick fix. Add these lines at then end of your main method :
if (args.length > 0) {
PrintStream out = null;
try {
out = new PrintStream(new FileOutputStream(args[0]));
out.print(passwd);
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (out != null) out.close();
}
}
And invoke your application like
$ java PasswdPrompt .out.tmp; less .out.tmp; rm .out.tmp
However, your prompted password will reside in plaintext (though hidden) file until the command terminates.
回答2:
So, for some reason, when System.console() returns null, terminal echo is always off, so my problem becomes trivial. The following code works exactly as I wanted. Thanks for all the help.
import java.io.*;
public class PasswdPrompt {
public static void main(String args[]) throws IOException{
Console cons = System.console();
char passwd[];
if (cons == null) {
// default to stderr; does NOT echo characters... not sure why
System.err.print("Password: ");
BufferedReader reader = new BufferedReader(new InputStreamReader(
System.in));
passwd= reader.readLine().toCharArray();
}
else {
passwd = cons.readPassword("Password: ");
}
System.err.println("Successfully got passwd.: " + String.valueOf(passwd));
}
}
来源:https://stackoverflow.com/questions/5326406/how-to-handle-java-passwd-reading-when-system-console-returns-null