我正在尝试为我的网站创建登录和注册页面。我希望使用cookie来跟踪用户会话,但我试图以最恰当和安全的方式实现它。我已经尝试过查看教程和论坛,但其中大部分已经过时,并且使用人们评论不安全的技术。我理解令牌需要随机生成和加密,所以我发现一个建议在UUID上使用MessageDigest的响应。但是我发现有更多的文章表明这可能不像我想的那样安全......有关生成cookie标记以存储在我的数据库中的安全方法的任何建议吗?
当我尝试使用UUID方法时,由于我无法找到如何将其转换为字符串,因此我无法将其放入数据库中。这是我的代码......
UUID uuid = UUID.randomUUID();
MessageDigest salt = MessageDigest.getInstance("SHA-256");
salt.update(uuid.toString().getBytes("UTF-8"));
答案 0 :(得分: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
这个令牌可以很好地使用,但有些人喜欢base64编码JSON。在这种情况下,我们最终得到类似的东西:
eyAiZXhwaXJ5IjogIjE6MzA6MDAgMjQvMTAvMjAxMiIsICJ1c2VySUQiOiAiRjY4RDRBNzdEQzM0IiB9.ScvlfpUDqgxtDPH4jsK44d+4cMNG+5yCvASJkVEI11o
我们很容易通过获取JSON对象,再次执行相同的操作,然后将HMAC的结果与附加到令牌的结果进行比较来验证此令牌是否合法。如果它们匹配,我们知道我们的服务器生成了令牌并且它是合法的。
答案 1 :(得分:1)
似乎对这种“安全”令牌的实际含义存在一些误解。
理论上它可以是任何东西。您可以使用用户名,增量ID计数器,或用户名的盐渍哈希,或者使用uuid。
问题是你用它做什么以及为什么?
如果您正在使用它,因为您只想了解请求的持续时间,那么一个数字就可以正常工作(理论上讲;不是说我推荐它,稍后会更多)。如果有人伪造身份证号码,你不会失去任何重大的东西,他们为什么会这样做?他们没有从中看到实际的好处。
如果您使用此令牌是因为它确定了用户的权限用户,那么显然您的目标是使其无法伪造。如果你想要它是假的,那么你应该让它真正随机和独特。因此,您可以非常轻松地使用UUID.randomUUID().toString()
- 这很可能是可欺骗的,因为有人需要知道机器上的精确纳秒精度以及知道随机状态的能力数字生成器用于uuid的其他位。这根本就不会发生。