Hashing然后存储令牌,需要多少费用?

时间:2015-09-12 12:27:30

标签: node.js mongodb security hash cryptography

我正在努力创造安全的东西,但并不可怕。

我需要的是在我的数据库中找到一个用户,然后编辑该用户的字段。 我目前这样做的方式是这样的代码:

exports.buyItem = function(req, res, next) {
var token = req.body.token;
var playerID = req.body.playerID;
User.findOne({ token: SHA256(token)+playerID },
///implementation ( do something for that user)

说明: 用户登录时,会创建随机生成的令牌。 然后将令牌发送回用户。 它也被散列并存储在数据库中(与playerID连接)

现在,每次我的用户向数据库发出请求时,他都会将令牌+ playerID发送到服务器,然后服务器验证,如上面的代码所示。 (它检查哈希标记+ playerID是否在数据库中)

现在,我的问题是:

  • 鉴于服务器会有大量流量,会计算 每次用户请求某个问题时哈希?(SHA256计算是否会破坏服务器?)
  • 您是否看到了实施方面的任何其他问题,您是否对我应该采取哪些不同的做法有所建议?

我不想使用cookies。

3 个答案:

答案 0 :(得分:0)

Imho计算每个请求的哈希是非常昂贵的。 我将尝试解释我的授权方法:

每次创建用户时,都会为他/她分配真正的硬令牌(在mongodb或* sql数据库中按字符串索引) https://github.com/vodolaz095/hunt/blob/master/lib/misc/rack.js#L19。 此随机字符串也有随机盐,使它们更难。

此令牌不会保存为用户会话的密钥。 Passport.js框架用于通过此密钥查找用户 https://github.com/vodolaz095/hunt/blob/master/lib/http/passport.js#L13

每次用户访问站点时,他/她都会使用此令牌提供此令牌,后端从数据库中提取用户。 它在一个512 RAM vps上为400-500个活跃用户工作。 我的主要优点是安全性 - 有一项功能可以为用户重新生成此令牌,如果来自此用户创建的所有会话,则会立即记录。

对于您的方法,我认为在每个请求上生成令牌的功能过于强大,我们可以Express Session通过https://github.com/vodolaz095/hunt/blob/master/lib/http/expressApp.js#L218-L226发出受保护和篡改的受保护会话。

并将唯一用户密钥(不是id)作为查询/正文参数传递给查找用户。

请注意secrethttpOnly标记 - 首先使会话Cookie值更加分区,第二个使会话只能通过浏览器访问,而不是通过客户端javascript

答案 1 :(得分:0)

我认为最好使用异步散列API(允许您进行回调的API),nodejs中的加密提供此功能。如果您使用同步(阻止)API,则您的nodejs在散列期间将无法执行任何其他操作。

作为参考,10 ^ 7 sha256s在我的电脑中需要38667ms(使用 sync API)。 (每个散列3μs,或259khash / s)

  

如果我让用户在他的机器上散列令牌然后将其与他的playerID一起上传,该怎么办?这样服务器只需要为用户进行查找。

如果你这样做,哈希就不会秘密提供。

我想你想要哈希的原因是为了在你的数据库泄露时保护用户免受黑客攻击。获取存储令牌的黑客将无法使用它,因为他需要找到原始令牌。但是如果你在客户端散列,黑客仍然可以使用该令牌,因为他只需要将其提交给服务器而无需知道原始令牌是什么。

答案 2 :(得分:0)

加密和散列是计算密集型的,但如果您需要安全性,则无法解决此问题。例如,如果您使用的是SSL,那么您的服务器正在加密和解密它发送和接收的所有内容。

我发现更大的瓶颈是在每个请求上访问磁盘数据库,这可以轻松增加100-200ms。所以我使用Redis作为令牌存储。相比之下,散列可能是几毫秒。

我正在创建一个接受各种身份验证提供程序的解决方案,并为每个用户生成随机令牌和密码。我将令牌存储在Redis中,以及密码的盐和哈希值。

我使用Passport的http承载策略来验证没有cookie的每个端点。用户发送标题: Authorization: Bearer token:password

然后我检查Redis是否有令牌,如果找不到,则终止请求。接下来,我哈希密码和盐来验证它。用户在几毫秒内进行身份验证。我选择了pbkdf2,但如果性能至关重要,SHA256会更快。

这是article比较各自的优点和缺点。

如果您不存储敏感数据,并且性能比安全性更重要,那么您可以将会话令牌存储为未散列的。散列的优点在于,即使有人侵入您的数据库,他们也无法使用他们所使用的数据来访问用户帐户。

但是肯定使用令牌的内存存储(例如Redis)会比MongoDB提供更好的性能。

我的项目SuperLogin是为CouchDB后端构建的,但欢迎您浏览源代码并对其进行反向工程。将它转换为MongoDB使用会很简单。