关于Java:为什么我们从char数组中的控制台读取密码而不是string

Why we read password from console in char array instead of String

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
Why is char[] preferred over string for passwords?

当我为OCPJP做准备时,我偶然遇到了一个主题——"从控制台读取用户输入"。

有一个例子,它在String引用中读取username,而在char[]数组中读取password,但我不明白它为什么使用char数组。代码如下:

1
2
3
4
Console console = System.console();

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

这引起了我的怀疑。为什么不使用字符串引用来存储密码?由于Strings是不可变的,所以在字符串中读取密码必须更安全,因为它的内容不能因此而更改。

那么,在读取char[]数组中的password中的要点是什么?

有人能对这件事有所了解吗?


正如您所说,字符串是不可变的,这意味着一旦您创建了字符串,如果另一个进程可以转储内存,那么在GC启动之前,您就无法除去数据(好的,可以进行反射)。

使用数组,您可以在完成后显式地擦除数据:您可以用所需的任何内容覆盖数组,并且密码在系统中的任何位置都不会出现,即使在垃圾收集之前也是如此。


从java.io.console的javadoc中:

Security note: If an application needs to read a password or other secure data,
it should use readPassword() or readPassword(String, Object...) and manually zero
the returned character array after processing to minimize the lifetime of
sensitive data in memory.

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

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


我相信这是因为当你不再需要它们的时候,你可以把它们从记忆中抹去。至少使用Java,如果使用字符串,则可能存在内存中剩余的副本。

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


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