要重置密码,我想向用户发送一个指向site / account / {hash}的链接,其中{hash}是用户密码的哈希值和时间戳。
我有以下代码只散列电子邮件并有一个可读的链接:
String check = info.mail;
MessageDigest md = MessageDigest.getInstance("SHA-1");
String checkHash = Base64.encodeBase64String(md.digest(check.getBytes()));
if(checkHash.equals(hash)){
return ResponseEntity.ok("Password reset to: " + info.password);
}else{
return ResponseEntity.ok("Hash didn't equal to: " + checkHash);
}
问题在于,当我将其转换为Base64时,它可能包含/标记会弄乱链接和检查哈希的内容。 我可以在散列后用其他东西替换任何不需要的符号,但是还有其他方法让你的散列只包含某些代码吗?
我也知道返回仍然是不安全的,但这只是用于测试和调试。
答案 0 :(得分:2)
RFC 3548 specifies a variant经常被称为" base64url"专为此目的而设计。在此变体中,+
和/
被-
和_
取代。
Java 8内置了对新Base64 class的支持。如果您坚持使用旧版本,则可以使用new Base64(true)
构造函数将Base64 class of Apache Commons配置为网址安全。
其他选项可能是:
不要使用Base64,但要将字节转换为十六进制 表示(不包含任何特殊字符):
String checkHash = toHex(md.digest(check.getBytes()));
与
private static String toHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02X", b));
}
return sb.toString();
}
对生成的哈希使用URL编码/解码(这是您已经知道的)