TLDR;
以 String.valueOf(charArray);
的形式通过 String 类解析 char 数组是否比创建 String 类的对象更安全?
我试图理解/扩展在以下方面的讨论:
Why is char[] preferred over String for passwords?
我最近阅读了很多关于如何在 Java 中“安全地”处理密码的内容,但仍有一个问题我不太清楚如何解决。当您从 jPasswordField 获取密码时,它以字符数组的形式出现。这很棒,因为您可以更轻松地用零覆盖数组,而不必等待垃圾收集器来清扫字符串等内容。
我的问题在于:当我想在 SQL 中运行更新语句来更新密码时,我根本无法放入字符数组,因为它是错误的格式。当我做类似 Arrays.toString(arrayName);
的事情时,我得到它的格式是:
[e, a, c, h, o, f, t, h, e, l, e, t, t, e, r, s]
我可以将它放入数据库列中的唯一方法......让我们说没有所有逗号和空格的 VARCHAR(100) 似乎是这样写的:
String stringPassword="";
int i=0;
for(char a:newPassword){
stringPassword=stringPassword+newPassword[i];
i++;
}
不过,如果我这样做,我不是就破坏了使用字符数组的全部意义吗?谷歌搜索并没有真正帮助我解决这个问题。
提前感谢您的宝贵时间。
编辑 1: 感谢 KKaar 提供可能的解决方案:
char[] passwordArray;
String.valueOf(passwordArray);
对于我需要它的目的,这在语法方面工作得很好,但我仍然不知道它是否安全。如果我在 preparedStatement 语法中创建 String.valueOf(passwordArray)
,它不会从中创建一个变量,但它仍然通过 String 类解析值。这是否意味着它仍然处于危险之中,还是安全的?
最佳答案
String.valueOf(charArray)
创建一个字符串,同样不安全。
现在可以使用 JDBC:
char[] password = ...;
try (PreparedStatement stmt = con.prepareStatement("...")) {
Reader reader = new CharArrayReader(password);
stmt.setCharacterStream(1, reader);
stmt.executeUpdate();
stmt.clearParameters();
}
Arrays.fill(password, ' ');
这确保在执行此代码后,没有对象 float 以进行垃圾收集,这可能会显示密码。
当然,前提是 JDBC 驱动程序不泄漏。 clearParameters 似乎有点过头了,但谁知道呢。
CharArrayReader 不会复制传递的数组,因此这也是安全的。
求具体代码:
String sql = "UPDATE teachers SET password=? WHERE firstname=? AND lastname=?";
try (PreparedStatement pStat = con.prepareStatement(sql)) {
Reader reader = new CharArrayReader(newPassword);
pStat.setCharacterStream(1, reader);
pStat.setString(2, firstName);
pStat.setString(3, lastName);
pStat.executeUpdate();
pStat.clearParameters();
}
Arrays.fill(newPassword, ' ');
由于语句应该被关闭,所以我冒昧地使用了一个局部变量。
关于Java char[] array jPasswordField处理和SQL更新语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50496916/