Как использовать сканер для чтения из STDIN в Java без вывода сообщений? - PullRequest
10 голосов
/ 24 мая 2010

Я хочу создать программу на Java, которая будет молча считывать пароль из STDIN. Я имею в виду, без вывода каких-либо нажатых символов в терминал и не скрывая его от истории командной строки и списка процессов операционной системы ps.

Ответы [ 4 ]

13 голосов
/ 24 мая 2010

Может быть полезен класс java.io.Console:

System.console().readPassword();

Это читает последовательность символов из консоли, не повторяя ничего. Обратите внимание, что это работает только при запуске вашего Java-приложения с реальной консолью. В противном случае System.console () возвращает ноль.

2 голосов
/ 08 января 2014

Менее безопасный вариант получения пароля через STDIN, который работает с фоновыми заданиями, виртуальными консолями и обычными консолями:

Это более совместимо и менее безопасно, оно должно работать с вашей виртуальной консолью в вашей IDE, для фоновых процессов, которые не имеют TTY, и обычных консолей. Когда консоль не найдена, она прибегает к использованию BufferedReader, который отображает пароль на экране, когда пользователь вводит его в некоторых случаях.

Java-код:

import java.io.*;
public class Runner {
    public static void main(String[] args) {
        String username = "Eric";

        try {
            ReadMyPassword r = new ReadMyPassword();
            char[] password = r.readPassword(
              "Hey %s, enter password to arm the nuclear wessels>", username);

            System.out.println("Exposing the password now: '" + 
                new String(password) + "'");

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
class ReadMyPassword{
    public char[] readPassword(String format, Object... args)
            throws IOException {
        if (System.console() != null)
            return System.console().readPassword(format, args);
        return this.readLine(format, args).toCharArray();
    }
    private String readLine(String format, Object... args) throws IOException {
        if (System.console() != null) {
            return System.console().readLine(format, args);
        }
        System.out.print(String.format(format, args));
        BufferedReader reader = new BufferedReader(new InputStreamReader(
                System.in));
        return reader.readLine();
    }
}

Вот как выглядит виртуальная консоль Eclipse:

Hey Eric, enter password to arm the nuclear wessels>12345
Exposing the password now: '12345'
Program Sisko 197 ready for implementation on your command

Вот как это выглядит через обычную консоль.

el@apollo:/home/el/bin$ java Runner
Hey Eric, enter password to arm the nuclear wessels>
Exposing the password now: 'abcdefg'
Program Sisko 197 ready for implementation on your command
el@apollo:/home/el/bin$
2 голосов
/ 24 мая 2010

Возможно, вы захотите дать java.io.Console взгляд

У него есть метод readPassword, который "Считывает пароль или фразу-пароль из консоли с отключенным эхом".

0 голосов
/ 08 января 2014

Самый безопасный вариант для Java получить пароль с помощью STDIN:

Это демонстрация с Java на терминале Ubuntu 12.10. Захват пароля с помощью STDIN является хорошей идеей в плане безопасности, поскольку пароль не отображается в истории командной строки или в списке процессов с ps. Введенные буквы пароля выбрасываются и не сохраняются.

Java-код:

public class Runner {
    public static void main(String[] args) {

        System.out.print("Enter password: ");

        String secretpassword = new String(System.console().readPassword());

        System.out.println("Here we expose our password to STDOUT: " 
            + secretpassword);

        //Put maximum levels of encapsulation and security on this
        //secretpassword variable.  Destroy it in memory asap, don't leave it
        //sitting around anywhere.
    }
}

Условия использования вышеуказанного кода

  1. Если ваш главный приоритет - сверхвысокая безопасность, даже не сохраняйте этот пароль в String. Зашифруйте его сразу после получения от пользователя. Таким образом, если какой-нибудь умный человек просканирует память вашей программы, он не найдет там ваш пароль в виде открытого текста.

  2. Если вы попытаетесь запустить эту программу через планировщик фоновых заданий, то вполне возможно, что System.console().readPassword() вернет исключение NullPointerException, которое является функцией повышения безопасности. Он запрещает доступ к таким махинациям, как виртуальные консоли и фоновые задачи. Если вы хотите, чтобы он работал правильно с виртуальными консолями, см. Мой другой ответ на этой странице.

  3. Если вы попытаетесь запустить этот код через IDE, такую ​​как Eclipse, Netbeans или любую другую виртуальную консоль, то System.console().readPassword() сгенерирует исключение NullPointerException, потому что реальная консоль не найдена, и программа остановится. Это особенность, а не ошибка.

Как выглядит консоль:

el@apollo:/home/el/test$ java Runner
Enter password: 
Here we expose our password to STDOUT: foobarpassword

el@apollo:/home/el/test$ 
...