在NodeJS,Crypto Token身份验证环境中生成唯一令牌

时间:2014-09-26 19:03:56

标签: node.js cryptojs

使用nodejs和crypto,现在,当用户登录时,我会生成一个随机身份验证令牌:

var token = crypto.randomBytes(16).toString('hex');

我知道这不太可能,但两个令牌的可能性很小。

这意味着用户理论上可以在另一个帐户上进行身份验证。

现在,我看到两种明显的方法来传递这个:

  • 当我生成令牌时,查询用户的数据库并查看是否有 具有相同值的令牌已存在。如果是的话,只需生成另一个。如您所见,由于我正在向数据库添加查询,因此这并不完美。
  • 由于每个用户在我的数据库中都有唯一的用户名,我可以 使用用户名作为秘密生成器密钥生成随机令牌。 这样,两个令牌就没有办法具有相同的价值。可以加密吗?它安全吗?

你会怎么做?

2 个答案:

答案 0 :(得分:14)

不太可能担心它偶然发生。我不会牺牲性能来锁定并检查数据库。

考虑一下Pro Git中关于20字节SHA-1总和之间随机冲突的可能性的摘录:

  

这是一个例子,可以让您了解获得a所需的内容   SHA-1碰撞[偶然]。如果地球上所有65亿人都在编程,   每一秒,每一个都产生相同的代码   整个Linux内核历史(100万Git对​​象)和推送   它进入一个巨大的Git存储库,需要5年时间   存储库包含足够的对象,具有50%的概率   单个SHA-1对象冲突。 [平均项目]存在的概率较高   你的编程团队成员将被狼攻击并杀死   在当晚的无关事件中。

(SHA-1碰撞can be directly constructed now,因此报价现在不太适用于SHA-1,但在考虑随机值的碰撞时它仍然有效。)

如果您仍然担心这种可能性,那么您可以轻松使用更多随机字节而不是16。

但是关于你的第二个想法:如果你用随机用户名对随机ID进行哈希处理,那么该哈希可能会发生冲突,就像随机ID一样。你还没有解决任何问题。

答案 1 :(得分:0)

您应该始终向数据库列添加UNIQUE约束。这将创建一个隐式索引来改进对此列的搜索,并确保两个记录中没有一个具有相同的值。因此,在最坏的情况下,您将获得数据库异常,而不是安全违规。

此外,根据需要创建唯一令牌的频率,我认为在大多数情况下在生成期间使用数据库查找是完全正常的。如果您的列再次被正确编入索引,则查询速度非常快。大多数数据库都具有良好的水平可扩展性,因此如果您正在构建下一个Facebook,那么它也是一种选择。此外,您可能还需要进行查询以检查电子邮件的唯一性。

最后,如果你真的关心性能,你总是可以预先生成一百万个独特的令牌,并将它们存储在单独的数据库表中以便快速使用。只需设置例程,定期检查其使用情况,并根据需要向其中插入更多记录。但是,正如@MacroMan在评论中所说,如果有人可以访问预先生成的令牌列表,这可能会产生安全隐患,因此应该避免这种做法。