开发者

How to handle java passwd reading when System.console() returns null?

开发者 https://www.devze.com 2023-02-17 17:18 出处:网络
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(),

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.");
    }
}


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.


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

}
0

精彩评论

暂无评论...
验证码 换一张
取 消