【问题标题】:How to read password from console without using System.console()?如何在不使用 System.console() 的情况下从控制台读取密码?
【发布时间】:2023-03-09 19:32:02
【问题描述】:

我点击了this eclipse bug,其中System.console() 不适用于Java 应用程序启动。我有一个小型 Java 应用程序,该应用程序还需要输入只能从 IDE 内启动的密码。有没有其他方法可以安全地仅使用 JDK 类从控制台读取密码(即不在控制台上显示)?

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

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

【问题讨论】:

  • 我认为这是一个很好的学习机会,看看您是否可以在没有 Eclipse 的情况下创建一个小型 Java 应用程序,只使用 javac 和可能的 ant。这比您想象的要容易!
  • @jrajav 这更像是一个安全问题,而不是简单的学习问题。
  • 我不认为在 Eclipse 控制台上隐藏密码的好方法。但是,你真的需要在 Eclipse 控制台上屏蔽密码吗? Eclipse 控制台仅供开发人员使用。一旦你部署了你的程序,我假设它会在最终用户操作系统上安装的 JVM 上运行。
  • @wns349 该应用不会部署在任何地方。它只是一个为我们开发人员重复工作的小应用程序。但通常开发人员都坐在一张桌子旁。

标签: java security console passwords


【解决方案1】:

也许代替控制台尝试使用带有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));

【讨论】:

    【解决方案2】:

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

    • 您不能使用System.in,因为它可能没有连接到控制台。

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

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


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

    【讨论】:

    • 那不是真的,有一种情况System.getConsole()返回nullSystem.in不是null,例如在这种情况下:stackoverflow.com/questions/4203646/system-console-returns-null
    • @DavidReichelt - 你指的是哪个答案?
    • @DavidReichelt - 无论如何,你所说的都是题外话。 System.in始终为非空!!! (除非您调用setIn(null) ...)关键是System.in 是否指向一个交互式控制台,该控制台可以在非回显模式下安全读取密码。
    • @StephenC:David Georg Reichelt 可能指的是这个答案(在提到的问题中):stackoverflow.com/a/11199326/1796我对 gradle 4、IntelliJ IDEA、JDK8 的个人经验是 System.console() 是null 但 System.in 不为空 AND 已连接到控制台,我能够正确读取它。
    【解决方案3】:

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

    所以我写了这个方法:

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

    这种解决方法的缺点是,在 Eclipse 中,您将在程序运行期间看到密码。

    【讨论】:

    • "(亲爱的 Eclipse 社区:修复那个 bug 有这么难吗?)" - 这不是 Eclipse 社区!如果你想告诉他们这个“错误”,他们有一个问题跟踪器。但除非你有一个切实可行的解决方案让他们实施,否则你可能会浪费你的呼吸......
    【解决方案4】:

    与@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 ) );
    

    【讨论】:

      猜你喜欢
      • 2011-10-16
      • 2019-12-06
      • 1970-01-01
      • 2020-01-01
      • 2016-12-19
      • 1970-01-01
      • 1970-01-01
      • 2014-01-22
      • 1970-01-01
      相关资源
      最近更新 更多