java 如何在不使用 System.console() 的情况下从控制台读取密码?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15159762/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 18:40:42  来源:igfitidea点击:

How to read password from console without using System.console()?

javasecurityconsolepasswords

提问by SpaceTrucker

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 safelyread a password (meaning not displaying it on the console) from the console with only using JDK classes?

我遇到了这个 Eclipse 错误System.console()它不适用于 Java 应用程序启动。我有一个小型 Java 应用程序,它也需要输入一个只能从 IDE 中启动的密码。有没有其他方法可以仅使用 JDK 类从控制台安全地读取密码(意味着不在控制台上显示它)?

EDIT:
I know of System.in, but that is displaying the inputed characters in the console and is therefore not safe.

编辑:
我知道System.in,但那是在控制台中显示输入的字符,因此不安全。

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.

EDIT2:
我还要注意的是,可以在windows下创建一个批处理文件,或者在项目中的linux/unix下创建一个小的bash脚本。通过使用系统默认编辑器在 eclipse 中打开此文件,它将在可用的新控制台窗口中启动System.console()。这样您就可以从 eclipse 中启动应用程序。但必须首先构建项目,以便二进制文件存在。

采纳答案by Stephen C

If System.console()returns null, that means that there is no usable console as far as Java is concerned.

如果System.console()返回null,则意味着就 Java 而言没有可用的控制台。

  • You can't use System.inbecause 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.

  • 您无法使用,System.in因为它可能未连接到控制台。

  • 即使可以,也没有可移植的方法来关闭 Java 中的回显。

  • 您也许可以使用 Swing(或其他任何方式)弹出一个窗口来询问密码,但如果系统是无头的,那将无法工作。



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.

如果您准备做不可移植的事情,那么(在 Linux / UNIX 上)您可以尝试打开“/dev/console”或“/dev/tty”。然后您可以使用 termios 将 tty 驱动程序置于 noecho 模式。但是您至少需要在本机代码中执行其中的一些操作。

回答by Pshemo

Maybe instead of console try using dialog with JPasswordField. Here is example from http://blogger.ziesemer.com/2007/03/java-password-dialog.html.

也许而不是控制台尝试使用带有JPasswordField. 这是来自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));

回答by Frank

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.

我遇到了同样的问题。(亲爱的 Eclipse 社区:修复那个 bug 这么难吗?)和其他人一样,我需要 IDE 用于开发/调试和独立运行。

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.

这种变通方法的缺点是,在 Eclipse 中,您将在程序运行时看到密码。

回答by krevelen

Similar to the answer given by @Pshemo, one could fall back to Swing:

与@Pshemo 给出的答案类似,人们可以回到 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 ) );