Java 为什么我们从控制台读取字符数组而不是字符串中的密码
可能重复:Java 为什么我们从控制台读取字符数组而不是字符串中的密码,java,console,Java,Console,可能重复: 当我在为OCPJP做准备的时候,我偶然碰到了一个主题——“从控制台读取用户输入” 有一个例子,它在String引用中读取username,而在char[]数组中读取password,但我不明白它为什么使用char数组。。代码如下:- Console console = System.console(); String username = console.readLine("User Name? "); char[] password = console.readPassword
当我在为OCPJP做准备的时候,我偶然碰到了一个主题——“从控制台读取用户输入” 有一个例子,它在
String
引用中读取username
,而在char[]
数组中读取password
,但我不明白它为什么使用char数组。。代码如下:-
Console console = System.console();
String username = console.readLine("User Name? ");
char[] password = console.readPassword("Password? ");
这使我产生了怀疑。。为什么我们不使用字符串引用来存储密码。由于字符串
是不可变的,因此读取字符串中的密码必须更安全,因为它的内容不能因此而更改
那么,在char[]
数组中读取password
有什么意义呢
有人能解释一下这个问题吗?由于字符串是不可变的,所以在应用程序处于活动状态时,它们不能被覆盖并保留在内存中。另一方面,
char
数组可以清除所有密码信息。正如您所说,字符串是不可变的,这意味着一旦您创建了字符串,如果另一个进程可以转储内存,那么在GC启动之前,您无法(好的,可以使用反射)清除数据
使用数组,您可以在处理完数据后显式地擦除数据:您可以用任何您喜欢的内容覆盖数组,并且即使在垃圾收集之前,密码也不会出现在系统中的任何位置。我认为这样做是为了在不再需要时通过覆盖来清除内存中的密码。至少在Java中,如果您使用字符串,那么内存中可能会有剩余的副本 如果使用for循环覆盖char数组并将每个值设置为0,我认为内存中不会有任何剩余副本。来自: 安全注意事项:如果应用程序需要读取密码或其他安全数据, 它应该使用
readPassword()
或readPassword(字符串、对象…)
并手动归零
处理后返回的字符数组,以最小化
内存中的敏感数据
这只是为了防止其他应用程序(如键盘记录器等)访问密码
此外,如果您使用
String
,因为它们是不可变的,修改它们将在内存中创建副本。在这种情况下,使用char[]
将节省您的时间。因为它们是可变的,它们不会创建副本,您可以在处理后将其设为null。不了解char[]可以不同于键盘记录程序的字符串…@caarlos0实际上,这不会阻止键盘记录程序,但会减少其读取内容的机会,因为副本不可用,数据将被取消。如果我错了,请纠正我,但是,我认为键盘记录程序会捕获键盘事件..所以,无论您使用的数据类型是什么..对吗?我相信这只会阻止人们从内存转储中获取字符串。由于焦点问题,他们无法直接从输入中获取密钥。相反,他们必须读取内存。嗯,在这种情况下,你是对的。谢谢。至少这是使用字符数组作为密码的目的。但是,我不确定是否考虑了堆碎片整理虚拟内存、交换等等都是真的。若对堆进行碎片整理导致字符数组在进程的内存空间内移动,那个么旧位置上的内容会被删除吗?我相信这取决于GC特定的实现。。。