1 回答
TA贡献1898条经验 获得超8个赞
这是我经历过这个过程的过程; 我在这里完整地写出来帮助你学习这个过程,而不仅仅是这个解决方案。
从ShaPasswordEncoder(为简洁起见删除注释)的来源:
public class ShaPasswordEncoder extends MessageDigestPasswordEncoder {
public ShaPasswordEncoder() {
this(1);
}
public ShaPasswordEncoder(int strength) {
super("SHA-" + strength);
}}对我来说,看起来像一个非常薄的包装类。呼叫new ShaPasswordEncoder(256)是有效地与调用new MessageDigestPasswordEncoder("SHA-256"),所以让我们来看看源说:
public class MessageDigestPasswordEncoder extends BaseDigestPasswordEncoder {
private final String algorithm;
private int iterations = 1;
[...]
public String encodePassword(String rawPass, Object salt) {
String saltedPass = mergePasswordAndSalt(rawPass, salt, false); /* 1 */
MessageDigest messageDigest = getMessageDigest();
byte[] digest = messageDigest.digest(Utf8.encode(saltedPass)); /* 2 */
// "stretch" the encoded value if configured to do so
for (int i = 1; i < this.iterations; i++) { /* 3 */
digest = messageDigest.digest(digest);
}
if (getEncodeHashAsBase64()) {
return Utf8.decode(Base64.encode(digest));
} else {
return new String(Hex.encode(digest)); /* 4 */
}
}
[...]}啊,现在我们到了某个地方。那里有一些额外的方法,但我们现在才真正关心encodePassword。它的工作原理与你期望的一样。从编号行:
加密密码
这使用了看起来很无辜的
mergePasswordAndSalt方法,我们接下来会看一下哈希盐渍密码
请注意这里的UTF-8编码 - 这并不总是默认编码
重复散列输出以进行其他迭代
请注意,
messageDigest.digest方法的输入和输出都是原始字节数组,而不是十六进制编码的字符串返回最终输出的十六进制编码字符串
正如所承诺的,这是mergePasswordAndSalt方法的来源:
protected String mergePasswordAndSalt(String password, Object salt, boolean strict) {
if (password == null) { /* 1 */
password = "";
}
if (strict && (salt != null)) { /* 2 */
if ((salt.toString().lastIndexOf("{") != -1)
|| (salt.toString().lastIndexOf("}") != -1)) {
throw new IllegalArgumentException("Cannot use { or } in salt.toString()");
}
}
if ((salt == null) || "".equals(salt)) {
return password;
} else {
return password + "{" + salt.toString() + "}"; /* 3 */
}}再次从编号部分:
检查空密码
检查是否存在
{和}字符; 由于下一点,这些是不允许的在表单中输出salted密码
password{salt}
在这里,我们看到为什么您尝试在PHP中复制此算法失败。
从这些信息中,看看是否可以构建一个行为相同的PHP函数。我将在今晚晚些时候编辑一个完整的PHP解决方案,当时我可以访问一个环境来测试它。
添加回答
举报
