我想知道在构建时实施全班级先决条件的最佳设计是什么。
让我举一个简单的例子。
我有一个代表安全字符串的类,例如密码。密码仅存储为其哈希表示。密码无法检查,只能根据尝试输入的值进行检查。
class Password {
private String passwordHash;
private Password(){};
public Password(String aPassword) {
setPassword(aPassword);
}
public void setPassword(String aPassword) {
passwordHash = hash(aPassword);
}
public boolean checkPassword(String attempt) {
return verify(attempt, passwordHash);
}
}
问题是如何设计哈希算法的选择。客户端代码必须能够从不同的哈希算法中进行选择。并且,在给定的应用程序中,所有密码必须使用相同的哈希算法。
因此,我定义了一个Hasher接口,
interface Hasher {
String hash(String password);
boolean verify(String attempt, String hash);
}
可能会有不同的Hasher实现。
class SimpleHasher implements Hasher {
public String hash(String password) { // native java String.hashCode()
return Integer.toString(password.hashCode(),16);
}
public boolean verify(String attempt, String hash) {
return attempt.hashCode()==Integer.valueOf(hash, 16);
}
}
class SecureHasher implements Hasher {
public String hash(String password) { // Secure SCrypt hash
return com.lambdaworks.crypto.SCryptUtil.scrypt(password,16384,8,1);
}
public boolean verify(String attempt, String hash) {
return com.lambdaworks.crypto.SCryptUtil.check(attempt,hash);
}
}
客户端代码必须选择一个实现并设置哈希器。在此之前,没有人可以实例化密码。并且一旦设置,哈希就无法更改。
这是设计决定。
当前,我声明了一个static private
变量,因此所有密码实例的哈希值都相同。并设置了强制它一次不能更改的设置器。
class Password {
static private Hasher hasher = null;
static public void setHasher(Hasher ahasher) throws Exception {
if (hasher!=null) throw new Exception("hasher cannot be changed");
hasher = ahasher;
}
....
并且构造函数确保已设置哈希器
class Password {
...
public Password(String aPassword) throws Exception {
if (hasher==null) throw new Exception("no hasher set yet");
setPassword(aPassword);
}
...
到目前为止,太好了。但是,在我看来,它看起来不太好。我想知道是否有一些通用的模式可以解决这个问题。所以我的问题是这种模式是否存在以及如何在我的情况下实现。
答案 0 :(得分:0)
我建议更改您的设计,并尝试以其他方式进行处理。 首先,进行一些重构。构造函数不应包含任何代码。其次,您可以创建一个哈希器接口。不过,我会将其重构为:
public interface Hash {
String hashed(String value);
boolean isValid(String hashed);
}
接下来,更改您的密码类别:
public class Password {
private String password;
private Hash hash;
public Password(String password, Hash hash) {
this.password = password;
this.hash = hash;
}
public boolean isValid(String password) {
return hash.hashed(this.password).equals(hash.hashed(password);
}
}
那将是一个优雅的设计。您只需要确保通过构造函数传递正确的哈希实现即可。设置好之后 每个密码将被验证为相同的实现。