Как читать пароль с консоли без использования System.console()?

Я ударил эту ошибку затмения, где System.console() недоступно для запуска приложений Java. У меня есть небольшое приложение Java, которое также требует ввода пароля, который запускается только из среды IDE. Есть ли другой способ безопасно читать пароль (то есть не отображать его на консоли) с консоли только с использованием классов JDK?

EDIT:
Я знаю System.in, но это отображает введенные символы в консоли и поэтому не безопасно.

EDIT2:
Я также хочу отметить, что можно создать пакетный файл под окнами или небольшой bash script под linux/unix в проекте. Открыв этот файл в eclipse с помощью системного редактора по умолчанию, он будет запущен в новом окне консоли, где System.console() доступен. Таким образом, вы можете запустить приложение из eclipse. но сначала нужно создать проект, чтобы существовали двоичные файлы.

Ответы

Ответ 1

Если System.console() возвращает null, это означает, что нет полезной консоли для Java.

  • Вы не можете использовать System.in, потому что есть вероятность, что он не подключен к консоли.

  • Даже если бы вы могли, нет портативного способа отключить эхо в Java.

  • Возможно, вы сможете использовать Swing (или что-то еще), чтобы всплывать окно с запросом пароля, но если система безголовая, которая не будет работать.


Если вы готовы делать не переносные вещи, то (в Linux/UNIX) вы можете попробовать открыть "/dev/console" или "/dev/tty". И тогда вы можете использовать termios, чтобы включить драйвер tty в режим noecho. Но вам потребуется сделать хотя бы часть этого в собственном коде.

Ответ 2

Возможно, вместо консоли попробуйте использовать диалог с 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));

Ответ 3

Я столкнулся с той же проблемой. (Дорогое сообщество Eclipse: неужели так сложно исправить эту ошибку?) Как и всем остальным, мне нужна среда IDE для dev/debug и автономная для работы.

Итак, я написал этот метод:

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 вы увидите пароль во время выполнения программы.

Ответ 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 ) );