生成安全cookie令牌以持久存储

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

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

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

你现在的方法很糟糕。 考虑一下攻击者我是否知道我的受害者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作为键来提供它,然后将其结果作为base64编码附加到JSON对象字节。 它有时也有助于使用分裂字符,比如“。”。

然后我们最终得到以下结果:

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

这个令牌可以很好地使用,但有些人喜欢base64编码JSON。 在这种情况下,我们最终得到类似的东西:

 eyAiZXhwaXJ5IjogIjE6MzA6MDAgMjQvMTAvMjAxMiIsICJ1c2VySUQiOiAiRjY4RDRBNzdEQzM0IiB9.ScvlfpUDqgxtDPH4jsK44d+4cMNG+5yCvASJkVEI11o 

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

关于这个“安全”令牌实际意味着什么似乎存在一些误解。

从理论上讲,它可以是任何东西。 您可以使用用户名,增量ID计数器,或用户名的盐渍哈希,或uuid。

问题是你用它做什么以及为什么?

如果您正在使用它,因为您只想了解请求的持续时间,那么一个数字就可以正常工作(理论上讲;不是说我推荐它,稍后会更多)。 如果有人伪造身份证号码,你不会失去任何重大的东西,他们为什么会这样做? 他们没有从中看到实际的好处。

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