为什么我们从char数组中的控制台读取密码而不是String

时间:2012-10-02 13:08:11

标签: java console

  

可能重复:
  Why is char[] preferred over string for passwords?

当我准备OCPJP时,我遇到了主题 - “从控制台读取用户输入”。

有一个示例,它在username引用中读取String,而在password数组中读取char[],但我无法理解为什么它使用了char数组。这是代码: -

Console console = System.console();

String username = console.readLine("User Name? ");
char[] password = console.readPassword("Password? "); 

这引起了我的疑问。为什么我们没有使用 String 引用来存储密码。由于 Strings 不可变,,因此在字符串中读取密码必须更安全,因为无法更改其内容。

那么,在password数组中阅读char[]的重点是什么..

任何人都能解释一下这件事吗?

4 个答案:

答案 0 :(得分:9)

正如你所说,字符串是不可变的,这意味着一旦你创建了字符串,如果另一个进程可以转储内存,就没有办法(好吧,可能有反射)你可以在GC启动之前摆脱数据。

使用数组,您可以在完成数据后显式擦除数据:您可以使用您喜欢的任何内容覆盖数组,并且即使在垃圾回收之前,密码也不会出现在系统的任何位置。 / p>

答案 1 :(得分:5)

来自Javadoc of java.io.Console

  

安全提示:如果应用需要读取密码或其他安全数据,   它应该使用readPassword()readPassword(String, Object...)并手动归零   处理后返回的字符数组,以最小化生命周期   内存中的敏感数据。

这只是为了防止其他应用程序(如键盘记录程序等)访问密码。

而且如果你使用String,因为它们是不可变的,修改它们会在内存中创建副本。在这种情况下,使用char[]可以节省您的时间。由于它们是可变的,因此它们不会创建副本,您可以在处理后将它们设为空。

答案 2 :(得分:4)

由于字符串是不可变的,因此在应用程序处于活动状态时,它们不能被覆盖并保留在内存中。另一方面,char数组可以清除所有密码信息。

答案 3 :(得分:4)

我相信你可以通过在你不再需要时覆盖它们来清除它们。至少使用Java,如果你使用String,那么内存中可能会有剩余的副本。

如果使用for循环覆盖char数组并将每个值设置为0,我认为内存中不会有任何剩余的副本。