【问题标题】:Generating a secure cookie token to store persistently生成安全的 cookie 令牌以永久存储
【发布时间】:2018-02-08 20:09:48
【问题描述】:

我正在尝试为我的网站创建登录和注册页面。我希望使用 cookie 来跟踪用户会话,但是我正在尝试以最适当和最安全的方式实现它。我尝试查看教程和论坛,但其中大多数都已过时,并且使用了人们评论不安全的技术。我知道令牌需要随机生成和加密,所以我发现了一个建议在 UUID 上使用 MessageDigest 的响应。但我发现更多文章表明这​​可能不像我想的那样安全......关于生成 cookie 令牌以存储在我的数据库中的安全方法有什么建议吗?

当我尝试使用 UUID 方法时,我陷入了如何将其放入我的数据库中,因为我无法找到如何将其转换为字符串。这是我的代码...

UUID uuid = UUID.randomUUID();
MessageDigest salt = MessageDigest.getInstance("SHA-256");
salt.update(uuid.toString().getBytes("UTF-8"));

【问题讨论】:

    标签: java security encryption cookies salt


    【解决方案1】:

    对于这个“安全”令牌的实际含义似乎存在一些误解。

    理论上可以是任何东西。您可以使用用户名、增量 id 计数器、用户名的加盐哈希或 uuid。

    问题是您使用它的目的是什么?为什么?

    如果您使用它是因为您只想了解请求需要多长时间的信息,那么一个数字就可以了(理论上;不是说我推荐它,稍后会详细介绍)。如果有人伪造身份证号码,你不会失去任何重大的东西,他们为什么会这样?他们看不到它的实际好处。

    如果您使用此令牌是因为它确定了用户的权限目的,那么显然您的目标是使它不会被伪造。如果你想让它被伪造,那么你应该让它真正随机和独特。所以你可以很容易地使用UUID.randomUUID().toString() - 这不太可能被欺骗,因为有人需要知道你机器上的精确纳秒精度以及知道随机数生成器状态的能力对于 uuid 的其他位。而这根本不会发生。

    【讨论】:

    • 感谢您的澄清,我将 cookie 用于用户许可目的。
    【解决方案2】:

    你目前的方法,嗯,相当糟糕。考虑一下我,一个攻击者,是否得知我的受害者 UUID 是某个值x。然后我可以简单地获取x 的 SHA-256 哈希并将其作为 cookie 存储在您的网站上。多田。我现在冒充我的受害者。

    也就是说,为登录系统生成令牌的一种非常安全的方法是相对相似的。考虑以下 JSON 对象:

    { "expiry": "1:30:00 24/10/2012", "userID": "F68D4A77DC34" }
    

    如果我们将此 JSON 对象作为 cookie 存储在客户端,这将是确定我们的用户是谁以及此对象何时过期以及用户需要再次登录的绝佳方式。

    但是等等,这行不通,因为任何人都可以更改用户 ID 或过期时间,而您的服务器不会知道!

    我们可以通过引入 HMAC 轻松解决这个问题。 HMAC 是一个散列消息验证码。我们首先生成(一次,永远)一个随机 HMAC 密钥,k,以在服务器上使用。此密钥应保留在服务器上并且永远不会被传输。

    当用户登录时,我们创建一个类似于上面的 JSON 对象,然后通过一个 HMAC(例如,HMAC-SHA256)以k 作为密钥,然后将其结果附加到JSON 对象作为 base64 编码字节。有时使用拆分字符也有帮助,比如“.”。

    然后我们得到以下结果:

    { "expiry": "1:30:00 24/10/2012", "userID": "F68D4A77DC34" }.ScvlfpUDqgxtDPH4jsK44d+4cMNG+5yCvASJkVEI11o
    

    这个令牌可以完全像那样使用,但有些人也喜欢对 JSON 进行 base64 编码。在这种情况下,我们最终会得到这样的结果:

    eyAiZXhwaXJ5IjogIjE6MzA6MDAgMjQvMTAvMjAxMiIsICJ1c2VySUQiOiAiRjY4RDRBNzdEQzM0IiB9.ScvlfpUDqgxtDPH4jsK44d+4cMNG+5yCvASJkVEI11o
    

    通过获取 JSON 对象,再次执行相同的操作,然后将 HMAC 的结果与附加到令牌的结果进行比较,我们很容易验证此令牌是否合法。如果它们匹配,我们就知道我们的服务器生成了令牌并且它是合法的。

    【讨论】:

    • 哦,我从未听说过这种技术。这似乎是一种更好的方法,我将研究如何实现它。谢谢。
    • 嗯...但是如果uuid 是坏的,因为它可以被盗,它也可以被盗。这里唯一的好处是它会过期。服务器可以轻松地发出一个新的uuid,然后它就不必对每个请求都进行加密验证。
    • @corisKa 我假设 uuid 是用户 ID。此外,您更愿意进行加密还是提出整个数据库请求?这种方法不需要数据库交互来验证。它几乎是 JWT 令牌,非常常见。很惊讶你居然没认出来。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-05
    • 2015-08-24
    • 1970-01-01
    • 2016-05-16
    • 2022-07-15
    • 2013-09-20
    相关资源
    最近更新 更多