20

可能重复:
为什么 char[] 优先于密码字符串?

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

有一个例子,它usernameString参考中读取,而passwordchar[]数组中,但我不明白为什么它使用 char 数组。这是代码: -

Console console = System.console();

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

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

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

任何人都可以在这件事上有所了解吗?

4

4 回答 4

11

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

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

于 2012-10-02T13:11:28.607 回答
6

来自java.io.Console 的 Javadoc

安全说明:如果应用程序需要读取密码或其他安全数据,它应该使用readPassword()readPassword(String, Object...)手动归零处理后返回的字符数组,以最大限度地缩短内存中敏感数据的生命周期。

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

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

于 2012-10-02T13:12:20.493 回答
5

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

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

于 2012-10-02T13:11:35.507 回答
4

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

于 2012-10-02T13:11:00.867 回答