在NodeJS,Crypto令牌authentication环境中生成独特的令牌

使用nodejs和crypto,现在,当用户login时,我生成一个随机auth令牌:

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

我知道这不太可能,但是两个代币具有相同的价值的可能性非常小。

这个用户理论上可以在另一个账户上进行authentication。

现在,我看到两个明显的方法来通过这个:

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

你会怎么做?

这是不太可能担心的偶然发生。 我不会牺牲性能来locking和检查数据库。

请考虑Pro Git的这段摘录20个字节的SHA1总和之间碰撞的机会:

下面是一个例子,让您了解如何获得SHA-1碰撞。 如果地球上所有的65亿人都在编程,每一秒钟,每个人都在生成相当于整个Linux内核历史(100万Git对​​象)的代码,并将其推入一个巨大的Git存储库,那么需要5年该存储库包含足够的对象,以使单个SHA-1对象冲突的概率为50%。 对于平均项目,更高的可能性是,你的编程团队的每个成员都会在同一天晚上被无关的事件中的狼袭击和杀死。

如果你仍然担心这个概率,你可以使用更多的随机字节而不是16。

但是关于你的第二个想法:如果你用随机的ID来散列随机ID,那么这个散列可能会碰撞,就像随机ID一样。 你没有解决任何问题。

你应该总是添加一个UNIQUE约束到你的数据库列。 这将创build一个隐式索引来改进对此列的search,并且将确保两个logging中没有任何一个具有相同的值。 所以,在最坏的情况下,你会得到一个数据库exception,而不是一个安全违规。

另外,根据需要创build独特的标记的频率,我认为在大多数情况下,在生成过程中使用数据库查找是完全正确的。 如果您的列再次被正确编入索引,那么这将是一个相当快的查询。 大多数数据库水平扩展性都很好,所以如果你正在构build下一个Facebook,它又是一个select。 此外,无论如何,你可能需要做一个查询来检查电子邮件的唯一性。

最后,如果您真的关心性能,您可以预先生成一百万个独特的令牌,并将它们存储在单独的数据库表中以便快速使用。 只需设置一个例程来定期检查它的使用情况,并根据需要插入更多的logging。

  • PostgreSQL唯一约束

  • MySQL:唯一的约束