【问题标题】:When using System.console() in Java, why do output pipes break?在 Java 中使用 System.console() 时,为什么输出管道会中断?
【发布时间】:2015-12-09 20:53:17
【问题描述】:

我正在使用 System.console().readPassword() 从终端读取密码并执行一组操作。这一切都很好,但是当尝试将输出通过管道传输到 grep、head、awk 等时,它会因 System.console() 返回 null 而中断。

这段代码应该复制它:

public class TestPiping
{
    public static void main(String[] args)
    {
        String password = new String(System.console().readPassword("Whats the password?"));
        System.out.println(password);
    }
}

然后编译运行它:

$ javac -g TestPiping.java
$ java TestPiping         
Whats the password?
hello
$ java TestPiping | head
Exception in thread "main" java.lang.NullPointerException
    at TestPiping.main(TestPiping.java:5)

为什么重定向的标准输出会影响标准输入?是否需要在不使用 java.io.console 的情况下手动读取密码?

【问题讨论】:

  • 你能把它作为参数传递吗?
  • 我已经实现了一个 '--password-file' 选项,但如果用户不需要更改密码技术来重定向标准输出,那就太棒了。

标签: java unix console pipe


【解决方案1】:

经过更多研究和阅读,我将结束这个问题。问题在于(正如@jshelto 所暗示的)控制台使用 JNI 接口来禁用终端中的文本回显,并在读取字符时执行一大堆其他低级操作。我反编译了 java.io.console 的东西来检查它。这也必须是跨平台的,所以它有点毛茸茸。我仍然无法确定返回 null 的决定是在哪里做出的,但它似乎与安全相关。即:如果对标准输入是否安全有任何疑问,则返回 null。

我发现的一个解决方法是实现一个线程,在您读取输入时使用 '\b' 字符擦除控制台文本。尽管它是 Console readPassword() 的通用替代方法,但在使用 unix 管道重定向 stdout 时它会中断。它也不是很可靠或优雅。详情请见http://www.cse.chalmers.se/edu/course/TDA602/Eraserlab/pwdmasking.html

最后,我刚刚决定在 Console() 返回 null 时强制用户使用“--password-file”选项。无论如何,这可能是大多数用户最终使用应用程序的方式,或者通过 GUI 输入密码会更容易。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-28
    • 1970-01-01
    相关资源
    最近更新 更多