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解决方案,当时我可以访问一个环境来测试它。
添加回答
举报