我以前从未想过,只是我使用了getPassword
返回字符数组的方法,并且我看到该getText
方法已弃用。但现在我想,为什么这种方法被弃用了?
Java 文档解释:
已弃用。从 Java 2 平台 v1.2 开始,由
getPassword
.获取由组件表示的文本的一部分。如果长度为 0,则返回一个空字符串。
出于安全原因,不推荐使用此方法。请改用该
getPassword
方法。
但是这些安全原因是什么?有什么想法吗?
先感谢您。
我以前从未想过,只是我使用了getPassword
返回字符数组的方法,并且我看到该getText
方法已弃用。但现在我想,为什么这种方法被弃用了?
Java 文档解释:
已弃用。从 Java 2 平台 v1.2 开始,由
getPassword
.获取由组件表示的文本的一部分。如果长度为 0,则返回一个空字符串。
出于安全原因,不推荐使用此方法。请改用该
getPassword
方法。
但是这些安全原因是什么?有什么想法吗?
先感谢您。
调用时getText
,您会得到一个可能不会更改(反射除外)的字符串(不可变对象),因此密码将保留在内存中,直到垃圾收集。
调用时getPassword
您会得到一个可能被修改的 char 数组,因此密码实际上不会留在内存中。
试试这个 :
String myPass=String.valueOf(passwordField.getPassword());
这样做的原因是,如果您以字符串而不是字符数组的形式请求密码,则包含密码的字符串现在将在 Java 运行时的内存中浮动一段未指定的时间。它可能会被恶意 Java 组件或外部程序从那里读取。
通过使用 char 数组,您可以验证密码,然后立即对其进行加扰。
这种行为背后的原因是 Java 字符串池(有关更多信息,请参见例如这个 SO 问题)。一旦您将该密码字段的内容转换为 a String
(如果您使用该getText
方法会发生这种情况) ,该密码就会String
被放入池中,并且可以被其他人读取。
如果您查看该getPassword
方法的实现(如作为对您的问题的评论发布的SO 问题@Garbage 中所见),您可以仔细地看到这避免了创建String
.
请注意,这也意味着您不应该做类似的事情
if ( Arrays.equals( "mySuperSecretPassword".toCharArray(), passwordField.getPassword() ) )
或者您仍然将密码放入池中,然后您可以轻松使用该getText
方法。
getText() 返回一个字符串,以便将字符串(作为标准 Java 行为)添加到字符串池中。字符串池由垃圾收集器清理,但仅在它起作用时(并且不能按需)。因此,即使不需要密码,密码也可以保留在池中,并且可以由其他 Java 进程读取。
getPassword() 返回一个字符数组。这些不是字符串,而是数组对象,因此尽管垃圾收集器需要时也会将它们删除,但它们不会保留在任何池中,并且其他 java 进程无法访问它们。
但是你必须小心你如何使用 getPassword() 读取的字符数组,因为如果我们将它转换为字符串,那么它会进入池,就像我们使用 getText() 一样糟糕。 ..