繁体   English   中英

如何使用 Scanner 从 Java 中的 STDIN 静默读取?

[英]How to use Scanner to read silently from STDIN in Java?

我想制作一个 Java 程序,它可以静默地从 STDIN 读取密码。 我的意思是,无需将任何按下的字符输出到终端,并将其从命令行历史记录和操作系统进程列表ps隐藏起来。

类 java.io.Console 可能有用:

System.console().readPassword();

这从控制台读取一系列字符,不回显任何内容。 请注意,它仅在您使用真正的控制台启动 Java 应用程序时才有效。 否则, System.console() 返回 null。

通过 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$

你可能想看看java.io.Console

它有一个 readPassword 方法,它“从控制台读取密码或密码短语并禁用回显”。

Java 使用 STDIN 获取密码的最安全选项:

此演示是在 Ubuntu 12.10 终端上使用 Java 进行的。 使用 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. 如果您尝试通过 Eclipse、Netbeans 或任何其他虚拟控制台之类的 IDE 运行此代码,则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$ 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM