屏蔽从控制台输入的密码:Java

Posted

技术标签:

【中文标题】屏蔽从控制台输入的密码:Java【英文标题】:Masking password input from the console : Java 【发布时间】:2011-12-29 14:51:44 【问题描述】:

如何从控制台输入中屏蔽密码?我正在使用 Java 6。

我尝试过使用console.readPassword(),但它不起作用。一个完整的例子实际上可能对我有帮助。

这是我的代码:

import java.io.BufferedReader;
import java.io.Console;
import java.io.IOException;
import java.io.InputStreamReader;

public class Test 
   
    public static void main(String[] args) 
       
        Console console = System.console();

        console.printf("Please enter your username: ");
        String username = console.readLine();
        console.printf(username + "\n");

        console.printf("Please enter your password: ");
        char[] passwordChars = console.readPassword();
        String passwordString = new String(passwordChars);

        console.printf(passwordString + "\n");
    

我收到 NullPointerException...

【问题讨论】:

console.readPassword() 到底是怎么工作的? 在控制台中运行,而不是在 IDE 中运行 此代码在 ide 中不起作用,请参阅我的更新答案。 所以我必须将项目导出为 jar 文件并从命令行运行?如果是这样,我这样做了,并得到了这个错误..“无法从 C:\......加载主类清单属性” 看看***.com/questions/2591516/… 【参考方案1】:

一个完整的例子?运行此代码:(注意:此示例最好在控制台中运行,而不是在 IDE 中运行,因为在这种情况下 System.console() 方法可能会返回 null。)

import java.io.Console;
public class Main 

    public void passwordExample()         
        Console console = System.console();
        if (console == null) 
            System.out.println("Couldn't get Console instance");
            System.exit(0);
        

        console.printf("Testing password%n");
        char[] passwordArray = console.readPassword("Enter your secret password: ");
        console.printf("Password entered was: %s%n", new String(passwordArray));

    

    public static void main(String[] args) 
        new Main().passwordExample();
    

【讨论】:

我刚刚得到另一个 NullPointerException...我不明白! 您是在 IDE 中运行它吗?代码不是在运行吗?为什么要投反对票? 对于那些获得空指针的人,从控制台运行它,从 Eclipse 这将不起作用 @Woot4Moo 你能解释一下为什么这是“高度不安全”吗?如果没有任何背景说明,单独的陈述对于促进理解并不是很有用(也不容易验证或反驳)。 担心将密码打印到控制台的行的内部内存安全风险没有多大意义。【参考方案2】:

您将使用Console 类

char[] password = console.readPassword("Enter password");  
Arrays.fill(password, ' ');

通过执行 readPassword 回显被禁用。此外,在验证密码后,最好覆盖数组中的任何值。

如果您从 ide 运行它会失败,请参阅此解释以获得完整的答案:Explained

【讨论】:

@Woot4Moo:您能否详细说明“接受的答案是不安全的!”。我看到您在读入密码后正在改写密码,但这似乎很愚蠢。无论您做什么,密码都会在内存中保存一段时间。即使您没有手动改写保存密码的内存,它也会被垃圾收集,并且内存会被其他东西重新填充。老实说,如果有人能够读取内存中的任意地址,我认为你应该有更大的担忧。 @ArtOfWarfare 如果“答案”发生变化:***.com/a/8138549/205426 正如我所说的那样,它不安全的原因是:new String(passwordArray) 为字符串池分配了一个新字符串在 JVM 的生命周期中“永远不会”消失。为了反驳您关于垃圾收集的说法,您可能不知道 String 类是“特殊的”并且不会获得 GCd。是的,我同意密码会在内存中保留一段时间,我只是碰巧尽可能地减少了这段时间。 @ArtOfWarfare 此外,任何像 JVM 一样复杂的系统都会遇到问题。自从我发表这篇文章以来的近 4 年里,已经发现了无数针对 JVM 的漏洞。因此,如果您自 2011 年以来在 Java 6 中运行 JVM,我敢打赌存在“任意内存”漏洞 覆盖数组中的字符值充其量只是一种创可贴。在从 Console 对象读取密码到 Arrays.fill() 方法完成之间,不能保证“密码”字符数组的内容没有在堆周围复制几次。现实情况是,在 Java 中安全处理内存中的密码根本不可能【参考方案3】:
Console console = System.console();
String username = console.readLine("Username: ");
char[] password = console.readPassword("Password: ");

【讨论】:

需要填写密码数组。【参考方案4】:

如果您正在处理 Java 字符数组(例如从控制台读取的密码字符),您可以使用以下 Ruby 代码将其转换为 JRuby 字符串:

# 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"

另见“https://***.com/a/27628738/4390019”和“https://***.com/a/27628756/4390019”

【讨论】:

【参考方案5】:

如果我们从控制台运行,给定的代码绝对可以正常工作。并且类中没有包名

您必须确定“.class”文件的位置。因为,如果为类指定了包名,则必须确保将“.class”文件保存在指定文件夹中。例如,我的包名称是“src.main.code”,我必须在主文件夹内、src 文件夹内创建一个代码文件夹并将 Test.class 放在代码文件夹中。那么它将完美运行。

【讨论】:

以上是关于屏蔽从控制台输入的密码:Java的主要内容,如果未能解决你的问题,请参考以下文章

密码屏蔽(输入显示为********)

电脑每次开机都需要输入root密码怎么解决?

ssh 坚持从控制台而不是标准输入读取密码

websphere 无法进入 管理控制台 输入完用户名密码后报java.lang.NullPointerException

如何从java控制台获得用户输入?

如何从java控制台获得用户输入?