我正在阅读其中一本java认证书中的java.io.Console
课程,可能我错过了上一章的基本内容,但有人可以解释下面的内容吗?
它提到,readPassword
方法返回一个字符数组而不是String,以防止潜在的黑客发现此字符串,然后找到密码。
字符数组如何更安全?如果您可以获取数组中的值,那么您是否可以创建一个脚本来循环遍历各种组合并最终找到密码?
答案 0 :(得分:13)
Console对象通过其readPassword方法支持安全密码输入。此方法有助于以两种方式保护密码输入。首先,它抑制回显,因此密码在用户屏幕上不可见。其次,readPassword返回一个字符数组,而不是String,因此密码可以被覆盖,一旦不再需要就将其从内存中删除。
这里的想法是,一旦验证了密码,就可以调用Arrays.fill(或等效的)来清空char数组,从那时起,密码就不再存储在内存中了。由于字符串是不可变的,因此字符串将保留在堆中,直到它被垃圾收集 - 如果它设法自己实现内部将永远不会,并且在任何其他情况下仍然可能“太长”。它一直存在,它可能容易被各种载体嗅探。
答案 1 :(得分:4)
这是最好的练习之一。它没有多大意义,但我们这样做是为了过上轻松的生活。
如果密码在内存中,缓冲区读取溢出可以允许它被读取。或者它可以保存在核心转储或休眠图像中。使用mutable char[]
允许在一个有希望的狭窄窗口之后销毁数据,只要它没有被复制到字符串中,复制到别处,它可能在缓冲区中,垃圾收集喜欢移动对象等等
Swing中有一个很有趣的例子,其中JPasswordField
提供了char[]
方式来读取数据,但是如果它有一个动作监听器,例如会从数据中创建一个String
(这是一种非常常用的方式)。
答案 2 :(得分:2)
String是一个不可变的类,当密码存储在String中时,你无法控制它的生命周期,这意味着它可以在内存中使用(并且受内存转储等影响)很长一段时间(即使它没有被实现,在JVM退出之前它将在内存中)。当它存储在字符数组中时,您可以清除该数组,从而在验证后从内存中删除密码。