使用nodejs和crypto,现在,当用户登录时,我会生成一个随机身份验证令牌:
var token = crypto.randomBytes(16).toString('hex');
我知道这不太可能,但两个令牌的可能性很小。
这意味着用户理论上可以在另一个帐户上进行身份验证。
现在,我看到两种明显的方法来传递这个:
你会怎么做?
答案 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在评论中所说,如果有人可以访问预先生成的令牌列表,这可能会产生安全隐患,因此应该避免这种做法。