9

Spring文档说记住我是通过在cookie中存储以下信息来实现的 -

base64(用户名 + ":" + expireTime + ":" + md5Hex(用户名 + ":" + expirationTime + ":" 密码 + ":" + key))

我有以下困惑-

  1. 为什么要使用像 MD5 这样的不安全哈希来消化信息,而不是使用 SHA-1 或 SHA-2。对于这么小的信息,这些对性能的影响会很大吗?

  2. 为什么要通过网络传输这些信息呢?为什么不在服务器上维护一个加密安全随机数和此信息的映射,只返回映射密钥作为 cookie。AFAIK 这是 Servlet API 使用的方法,被认为更安全。

4

2 回答 2

10

让我们从第二个问题开始,因为它更相关:

第二个问题“为什么要通过网络传输密码......”答案:

因为你描述的只是Simple Hash-Based Token Approach

如果向下滚动页面Spring Security Reference: Chapter 10 Remember-Me Authentication你会看到 spring security 也可以使用不同的 remember me 方法:Chapter 10.3 Persistent Token Approach。这就是您在第二个问题中提出的建议。


第一个问题:简短回答“对于这么小的信息,这些对性能的影响会很大吗?” - 不

因此,如果您想使用Simple Hash-Based Token ApproachMD5 并且觉得 MD5 是不安全的,那么您可以继承TokenBasedRememberMeService [javadoc]并覆盖该String makeTokenSignature(long tokenExpiryTime, String username, String password)方法。例如(未经测试)

protected String makeTokenSignature(long tokenExpiryTime, String username, String password) {
    String data = username + ":" + tokenExpiryTime + ":" + password + ":" + getKey();
    MessageDigest digest;
    try {
        digest = MessageDigest.getInstance("SHA-256");
    } catch (NoSuchAlgorithmException e) {
        throw new IllegalStateException("No SHA-256 algorithm available!");
    }

    return new String(Hex.encode(digest.digest(data.getBytes())));
}
于 2012-04-20T06:27:35.313 回答
5

Simple Hash-Based 令牌使用的 MD5 哈希不是该方法的漏洞。

使用 MD5 散列密码是危险的,因为给定现有密码的散列值,您可以找到另一个散列到相同值的密码(使用彩虹表)。

但是,在这种情况下,MD5 不用于散列密码,而是用作MAC。如果您确实使用彩虹表来找到与该哈希冲突的值,那么您如何准确地使用该值?

对 cookie 使用不同的散列函数可能会让您感觉更安全,但在这种情况下它不会提供更多安全性。

如果您想要更高的安全性,那么您应该使用持久哈希令牌方法。简单哈希令牌以明文形式公开用户名,容易受到重放攻击。Persistent Token 避免了这些问题。

无论哪种方式,您都应该通过设置其 Secure 和 Http-only 标志来保护您的 remember-me cookie。

于 2012-04-21T04:20:15.257 回答