Ukryj wejście w wierszu poleceń

Wiem, że interfejsy linii poleceń, takie jak Git i inne, są w stanie ukryć dane wejściowe od użytkownika (przydatne dla haseł). Czy jest sposób, aby programowo to zrobić w Javie? Biorę hasło od użytkownika i chciałbym, aby jego dane wejściowe były "ukryte" na tej konkretnej linii (ale nie na wszystkich). Oto Mój kod na to (choć wątpię, że byłby pomocny...)

try (Scanner input = new Scanner(System.in)) {
  //I'm guessing it'd probably be some property you set on the scanner or System.in right here...
  System.out.print("Please input the password for " + name + ": ");
  password = input.nextLine();
}
Author: kentcdodds, 2012-05-30

6 answers

Spróbuj java.io.Console.readPassword. Musisz jednak uruchomić przynajmniej Javę 6.

   /**
    * Reads a password or passphrase from the console with echoing disabled
    *
    * @throws IOError
    *         If an I/O error occurs.
    *
    * @return  A character array containing the password or passphrase read
    *          from the console, not including any line-termination characters,
    *          or <tt>null</tt> if an end of stream has been reached.
    */
    public char[] readPassword() {
        return readPassword("");
    }

Uważaj jednak, to nie działa z konsolą Eclipse. Musisz uruchomić program z true console/shell/terminal / prompt, aby móc go przetestować.

 79
Author: adarshr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-02 12:51:14

Tak można zrobić. Jest to tzw. maskowanie wejściowe wiersza poleceń. Możesz to łatwo wdrożyć.

Możesz użyć osobnego wątku, aby usunąć znaki echa podczas wprowadzania i zastąpić je gwiazdkami. Odbywa się to za pomocą klasy EraserThread pokazanej poniżej

import java.io.*;

class EraserThread implements Runnable {
   private boolean stop;

   /**
    *@param The prompt displayed to the user
    */
   public EraserThread(String prompt) {
       System.out.print(prompt);
   }

   /**
    * Begin masking...display asterisks (*)
    */
   public void run () {
      stop = true;
      while (stop) {
         System.out.print("\010*");
     try {
        Thread.currentThread().sleep(1);
         } catch(InterruptedException ie) {
            ie.printStackTrace();
         }
      }
   }

   /**
    * Instruct the thread to stop masking
    */
   public void stopMasking() {
      this.stop = false;
   }
}

Z użyciem tego wątku

public class PasswordField {

   /**
    *@param prompt The prompt to display to the user
    *@return The password as entered by the user
    */
   public static String readPassword (String prompt) {
      EraserThread et = new EraserThread(prompt);
      Thread mask = new Thread(et);
      mask.start();

      BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
      String password = "";

      try {
         password = in.readLine();
      } catch (IOException ioe) {
        ioe.printStackTrace();
      }
      // stop masking
      et.stopMasking();
      // return the password entered by the user
      return password;
   }
}

Ten Link podyskutuj o szczegółach.

 12
Author: Vijay Shanker Dubey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-04 20:52:22

JLine 2 może być interesujący. Oprócz maskowania postaci, zapewni on funkcje uzupełniania, edycji i historii wiersza poleceń. W związku z tym jest to bardzo przydatne dla narzędzia Java opartego na CLI.

Aby zamaskować wejście:

String password = new jline.ConsoleReader().readLine(new Character('*'));
 8
Author: Brian Agnew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-26 13:14:58

Jest :

Console cons;
char[] passwd;
if ((cons = System.console()) != null &&
    (passwd = cons.readPassword("[%s]", "Password:")) != null) {
    ...
    java.util.Arrays.fill(passwd, ' ');
}

Źródło

Ale nie sądzę, aby to działało z IDE jak Eclipse, ponieważ program jest uruchamiany jako proces w tle, a nie Proces najwyższego poziomu z oknem konsoli.

Innym podejściem jest użycie JPasswordField w huśtawce z towarzyszącą actionPerformed metodą:

public void actionPerformed(ActionEvent e) {
    ...
    char [] p = pwdField.getPassword();
}

Źródło

 3
Author: Dhruv Gairola,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-30 15:42:04

Klasa Console ma metodę readPassword(), która może rozwiązać twój problem.

 0
Author: rlinden,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-30 15:39:34

Jeśli masz do czynienia z tablicą znaków Javy (taką jak znaki haseł, które czytasz z konsoli), możesz przekonwertować ją na ciąg JRuby za pomocą następującego kodu Ruby:

# GIST: "pw_from_console.rb" under "https://gist.github.com/drhuffman12"

jconsole = Java::java.lang.System.console()
password = jconsole.readPassword()
ruby_string = ''
password.to_a.each {|c| ruby_string << c.chr}

# .. do something with 'password' variable ..    
puts "password_chars: #{password_chars.inspect}"
puts "password_string: #{password_string}"

Zobacz też " https://stackoverflow.com/a/27628738/4390019 " i " https://stackoverflow.com/a/27628756/4390019 "

 -4
Author: Daniel Huffman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:33:13