从JavaFX中的PasswordField获取密码的安全方法

从JavaFX中的PasswordField获取密码的安全方法,java,javafx,Java,Javafx,有没有办法从JavaFX8中的PasswordField安全地检索密码,使其不保存在内存中 标准选项: String pass = passwordField.getText(); 这对我来说还不够。我期待着这样的事情: char[] pass = passwordField.getPassword(); 与许多事情一样,您可以使用反射来实现这一点。由于您使用的是反射,所以它不会很漂亮(只要看看所有这些异常),但我认为这是目前唯一的方法 public class SafePasswordFi

有没有办法从JavaFX8中的PasswordField安全地检索密码,使其不保存在内存中

标准选项:

String pass = passwordField.getText();
这对我来说还不够。我期待着这样的事情:

char[] pass = passwordField.getPassword();

与许多事情一样,您可以使用反射来实现这一点。由于您使用的是反射,所以它不会很漂亮(只要看看所有这些异常),但我认为这是目前唯一的方法

public class SafePasswordField extends PasswordField {

    public final char[] getPassword() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
        Content c = getContent();

        Field fld = c.getClass().getDeclaredField("characters");
        fld.setAccessible(true);

        StringBuilder sb = (StringBuilder) fld.get(c);
        char[] result = new char[sb.length()];
        sb.getChars(0, sb.length(), result, 0);

        return result;
    }

}

getContent()
返回的
内容始终是
javafx.scene.control.TextField$TextFieldContent的实例,因此可以安全地访问
字符
字段。

无论变量类型是什么(字符串,字符[…)它将始终存储在内存中,直到垃圾收集器把它捡起来。虽然我认为这会有点困难,但您必须编写一个程序并读取包含变量数据的内存空间,以便检索密码。如果我是你,我就不会担心任何窃听:)

那么你担心密码“保持”有效,因为它可能已添加到JVM字符串池中?我只是想知道:即使你可以从PasswordField中检索字符数组。。。这不会阻止该组件在内部使用字符串;这样你就什么也得不到了。对,这扩展了标准的TextField,但我希望像JavaSE中的JPasswordField这样的安全版本存在。我认为这个问题是正确的,因为使用字符数组作为密码是推荐的方法,例如JPasswordField()和PasswordCallback()@Krzysiek非常有趣;关于JPasswordField的Oracle教程讨论了很多安全问题;还有一个是JavaFXPasswordField。。。甚至都没提到。也许你想给甲骨文公司的人写一张bug通知单,看看他们有什么要说的。即使是char[]也帮不了那么多忙。输入密码后,内存将包含更多输入密码的痕迹,而不仅仅是密码字段本身的值。例如,每次按键都会产生一个KeyEvent,其中包含对按键的引用。此外,PasswordField具有撤消/重做功能,可生成密码的其他副本。此外,GC可能会将密码复制到无法访问的内存位置。因此,使用char[]作为文本属性并在使用后进行零填充不足以避免密码可能保留在内存中。同意-关于这篇@Tron非常有趣且相关的文章,有一个非常好的主题!当然值得一看。但是如果您将其存储为一个字符数组,那么您可以决定在使用完该数组后使用例如“0s”来覆盖该数组。与等待GC运行(您无法控制)相反,这并不能真正实现目标,因为它正在从
StringBuilder
复制到一个新数组,因此用户的密码仍将在内存中,并可以由内存分析器或堆转储提取。Swing的JPasswordField提供了对数组的直接访问,因此在不再需要时可以覆盖该数组,并防止从内存中提取该数组。