为什么不推荐使用JPasswordField中的getText()?

时间:2012-05-04 05:48:17

标签: java swing jpasswordfield

我之前从未想过,只有我使用返回字符数组的方法getPassword,我看到getText方法已弃用。但现在我认为,为什么这种方法已弃用?。

Java文档说明:

  

已过时即可。 从Java 2平台v1.2开始,由getPassword替换。

     

获取组件表示的部分文本。返回一个   如果长度为0,则为空字符串。

     

出于安全考虑,这种方法是   弃用。请改用getPassword方法。

但那些 安全原因 是什么?有关于此的任何想法吗?

提前谢谢。

5 个答案:

答案 0 :(得分:41)

调用getText时,会得到一个可能无法更改的String(不可变对象)(反射除外),因此密码会保留在内存中,直到收集垃圾。

当调用getPassword时,你得到一个可能被修改的字符数组,所以密码真的不会留在内存中。

答案 1 :(得分:13)

试试这个:

RESULT:

答案 2 :(得分:8)

这样做的原因是,如果您要求将密码设置为字符串而不是字符数组,则包含密码的字符串现在将在Java运行时的内存中浮动一段时间。可以想象,可以从那里读取流氓Java组件或外部程序。

通过使用char数组,您可以验证密码,然后立即对其进行加密。

答案 3 :(得分:5)

此行为背后的原因是Java字符串池(有关详细信息,请参阅例如this SO question)。只要将该密码字段的内容转换为String(如果使用getText方法会发生这种情况),String就会被放入池中,并且可以读取由其他人。

如果您要查看getPassword方法的实现(可以在SO question @Garbage中看到,作为对您的问题的评论),您可以看到这一点,小心避免创建{{ 1}}。

请注意,这也意味着您不应该执行类似

的操作
String

或者您仍然最终将密码放入池中,然后您可以轻松地使用if ( Arrays.equals( "mySuperSecretPassword".toCharArray(), passwordField.getPassword() ) ) 方法。

答案 4 :(得分:0)

  • getText () 返回一个字符串,以便将字符串添加到字符串池中(作为标准 Java 行为)。字符串池由垃圾收集器清理,但仅在它起作用时(并且不能按需)。因此,即使不需要密码,密码也可以保留在池中,并且可以被其他 Java 进程读取。

  • getPassword() 返回一个字符数组。这些不是字符串,而是数组对象,所以虽然在垃圾收集器需要的时候也会被删除,但它们不会留在任何池中,其他java进程无法访问。

但是你必须小心你如何使用getPassword()读取的字符数组,因为如果我们将它转​​换为String,那么它就会进入池中,就像我们使用getText一样糟糕() ...