我曾经看过Douglas的一次演讲,在javascript的上下文中,他提到在闭包中存储秘密可能是有用的。
我认为这可以在Java中像这样天真地实现:
public static Supplier<String> passwordStore(String encryptedPassword){
String plainTextPassword = encryptedPassword; //do some decryption
return () -> plainTextPassword;
}我想知道:这样做有什么好处吗?是不是在某种程度上不那么安全?
发布于 2017-10-12 11:39:24
下面是一个非常“工程”的例子,这样就不会在代码中使用IT了。
我认为,这种效果可以通过谓词而不是供应商来更好地演示。
假设您实现了密码检查器,如下所示:
public class PasswordChecker {
private final String secretPassword;
public PasswordChecker(String secretPassword) {
this.secretPassword = secretPassword;
}
public boolean test(String password) {
return Objects.equals(this.secretPassword, password);
}
}然后,您可以创建一个实例,然后传递它:
final PasswordChecker passwordChecker = new PasswordChecker("changeit");在其他地方,你可以用它来检查密码:
assertThat(passwordChecker.test("foobar")).isFalse();但是,对于手头有PasswordChecker实例的客户端来说,使用某种反射提取密码并不是那么困难:
Field secretPasswordField = passwordChecker.getClass().getDeclaredField("secretPassword");
secretPasswordField.setAccessible(true);
String secretPassword = (String) secretPasswordField.get(passwordChecker);
System.out.print(secretPassword);现在有一个结论也是一样的:
final String secretPassword = "changeit";
final Predicate<String> passwordChecker = password -> Objects.equals(secretPassword, password);现在您不能从secretPassword中提取passwordChecker。
发布于 2017-10-12 11:34:43
没有理由这么做。将密码存储在字符数组中,因为如果要打印出来,必须将它们显式转换为字符串。
请考虑以下示例:
String stringPassword = "password";
char[] charactersPassword = new char[]{'p','a','s','s','w','o', 'r', 'd'};
System.out.println("Password: " + stringPassword); // Password: password
System.out.println("Password: " + charactersPassword); // Password: [C@6ce253f1主要思想是您可以清除数组的项,因为它不是不可变的(@Klitos Kyriacou)。
Arrays.fill(charactersPassword, '0');此外,如果您将密码存储为纯文本字符串(它是不可变的),那么它将在内存中长期可用(在某种程度上仍然是可访问的),直到垃圾收集器处理它为止。
无论如何,强烈建议您注意一些安全库,它比发明一种新的(通常仍然有风险的)方法更能处理这些问题。
https://stackoverflow.com/questions/46708302
复制相似问题