当我准备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[]
的重点是什么..
任何人都能解释一下这件事吗?
答案 0 :(得分:9)
正如你所说,字符串是不可变的,这意味着一旦你创建了字符串,如果另一个进程可以转储内存,就没有办法(好吧,可能有反射)你可以在GC启动之前摆脱数据。
使用数组,您可以在完成数据后显式擦除数据:您可以使用您喜欢的任何内容覆盖数组,并且即使在垃圾回收之前,密码也不会出现在系统的任何位置。 / p>
答案 1 :(得分:5)
安全提示:如果应用需要读取密码或其他安全数据, 它应该使用
readPassword()
或readPassword(String, Object...)
并手动归零 处理后返回的字符数组,以最小化生命周期 内存中的敏感数据。
这只是为了防止其他应用程序(如键盘记录程序等)访问密码。
而且如果你使用String
,因为它们是不可变的,修改它们会在内存中创建副本。在这种情况下,使用char[]
可以节省您的时间。由于它们是可变的,因此它们不会创建副本,您可以在处理后将它们设为空。
答案 2 :(得分:4)
由于字符串是不可变的,因此在应用程序处于活动状态时,它们不能被覆盖并保留在内存中。另一方面,char
数组可以清除所有密码信息。
答案 3 :(得分:4)
我相信你可以通过在你不再需要时覆盖它们来清除它们。至少使用Java,如果你使用String,那么内存中可能会有剩余的副本。
如果使用for循环覆盖char数组并将每个值设置为0,我认为内存中不会有任何剩余的副本。