首页 > 解决方案 > Java char[] 数组 jPasswordField 处理和 SQL 更新语句

问题描述

TLDR;通过String类解析char数组,是String.valueOf(charArray);不是比制作String类的对象更安全?我试图理解/扩展以下讨论: 为什么 char[] 优于 String 的密码?

我最近刚刚阅读了很多关于如何在 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 类解析值。这是否意味着它仍然处于危险之中,或者它是否安全?

标签: javasql

解决方案


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, ' ');

这样可以确保在执行此代码后,没有对象会四处飘荡以进行垃圾收集,这可能会显示密码。

当然,前提是 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, ' ');

由于该语句应该被关闭,我冒昧地使用了一个局部变量。


推荐阅读