【问题标题】:Why getText() in JPasswordField was deprecated?为什么不推荐使用 JPasswordField 中的 getText()?
【发布时间】:2012-05-13 16:07:59
【问题描述】:

我以前从未想过,只是我使用了返回字符数组的方法getPassword,并且我看到getText 方法被弃用。但现在我想,为什么这种方法被弃用?。

Java 文档说明:

已弃用从 Java 2 平台 v1.2 开始,被 getPassword 取代。

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

出于安全原因,此方法是 已弃用。请改用getPassword 方法。

但是那些安全原因是什么?对此有何想法?

提前谢谢你。

【问题讨论】:

标签: java swing jpasswordfield


【解决方案1】:

调用getText 时,您会得到一个不可更改的字符串(不可变对象)(反射除外),因此密码会一直保留在内存中,直到垃圾回收。

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

【讨论】:

    【解决方案2】:

    试试这个:

    String myPass=String.valueOf(passwordField.getPassword());
    

    【讨论】:

    • OP 没有询问如何以String 形式获取密码;他在问*为什么密码返回为CharrArray 而不是String
    【解决方案3】:

    这样做的原因是,如果您以字符串而不是字符数组的形式请求密码,则包含密码的字符串现在将在 Java 运行时的内存中浮动一段未指定的时间。它可能会被恶意 Java 组件或外部程序从那里读取。

    通过使用字符数组,您可以验证密码,然后立即对其进行打乱。

    【讨论】:

      【解决方案4】:

      这种行为背后的原因是 Java 字符串池(参见例如 this SO question 了解更多信息)。一旦您将该密码字段的内容转换为String(如果您使用getText 方法会发生这种情况),String 就会被放入池中,并且可以被其他人读取。

      如果您想查看getPassword 方法的实现(如作为对您问题的评论发布的SO question @Garbage 中所见),您可以仔细地看到这避免了创建String

      注意,这也意味着你不应该做类似的事情

      if ( Arrays.equals( "mySuperSecretPassword".toCharArray(), passwordField.getPassword() ) )
      

      或者您最终还是将密码放入池中,然后您可以轻松使用getText 方法。

      【讨论】:

      • “Java 字符串池”用于编译时的实习常量。我质疑标准的 Swing 文本输入 really 是否实习输入了其中的文本值。我的理解是返回一个 char[] 数组而不是不可变的 String 允许密码立即清零,以最大限度地减少工作内存中的暴露/可见性(安全最佳实践)。无论哪种方式,都不会期望字符串为interned。
      【解决方案5】:
      • getText() 返回一个字符串,以便将字符串(作为标准 Java 行为)添加到字符串池中。字符串池由垃圾收集器清理,但仅在它起作用时(并且不能按需)。因此,即使不需要密码,密码也可以保留在池中,并且可以被其他 Java 进程读取。

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

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

      【讨论】:

        猜你喜欢
        • 2016-02-23
        • 2017-11-04
        • 2011-10-22
        • 2011-04-11
        • 2021-10-12
        • 2012-12-07
        • 2012-05-16
        • 2020-06-29
        相关资源
        最近更新 更多