有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Spring安全身份验证管理漏洞

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

base64(username + ":" + expirationTime + ":" + md5Hex(username + ":" + expirationTime + ":" password + ":" + key))

我有以下困惑——

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

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


共 (2) 个答案

  1. # 1 楼答案

    让我们从第二个问题开始,因为这是一个更相关的问题:

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

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

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


    第一个问题:简短回答“对于这样一小部分信息,这些信息对性能的影响会很重要吗?”-没有

    因此,如果您想使用Simple Hash-Based Token Approach并感觉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())));
    }
    
  2. # 2 楼答案

    基于简单哈希的令牌使用的MD5哈希不是该方法的漏洞

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

    然而,在本例中,MD5不是用来散列密码,而是用作MAC。如果您确实使用彩虹表来查找与该哈希冲突的值,那么您如何确切地使用该值

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

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

    无论哪种方式,您都应该通过设置“记住我”cookie的“安全”和“仅限Http”标志来保护它