我从官方 Java 教程页面控制台 - Java 教程
改编了这段代码public class RedirectOutputStreamExample {
public static void main(String[] args) throws InterruptedException {
Console c = System.console();
if (c == null) {
System.err.println("No console.");
System.exit(1);
}
String login = ((Console) c).readLine("Enter your login: ");
char [] oldPassword = c.readPassword("Enter your old password: ");
if (verify(login, oldPassword)) {
boolean noMatch;
do {
char [] newPassword1 = c.readPassword("Enter your new password: ");
char [] newPassword2 = c.readPassword("Enter new password again: ");
noMatch = ! Arrays.equals(newPassword1, newPassword2);
if (noMatch) {
c.format("Passwords don't match. Try again.%n");
} else {
c.format("Password for %s changed.%n", login);
}
Arrays.fill(newPassword1, ' ');
Arrays.fill(newPassword2, ' ');
System.out.println("password is: "+newPassword1);
System.out.println("password is: "+newPassword2);
} while (noMatch);
}
Arrays.fill(oldPassword, ' ');
System.out.println(oldPassword);
Thread.sleep(60000);
}
}
三个密码被覆盖后,它们将打印为空行(如预期)。 如您所见:
(我必须在控制台中执行此操作,因为 IntelliJ 终端存在安全问题并抛出错误“无控制台”)
但是,程序停止后,使用 jmap 和进程 ID 创建了内存转储。
我输入的密码在内存转储中仍然可见,如您所见:
这怎么可能?我做错什么了吗?我的 JVM 中是否存在较弱的默认安全配置?
我询问了 ChatGPT,它建议控制台在其内部操作中使用字符串。
只要你不知道
change()
在做什么,这绝对是可能的。如果您确实偏执地认为这可能不会发生,那么您应该使用 J9 JVM;它不会将值转储到常规堆转储中。
否则,从heapdump的截图来看,我想说,在不知道密码的情况下,很难将字符串识别为密码。