MongoDB _id
字段是否足够随机/不可猜测以充当 secret 数据?
例如:如果我正在构建服务器端 OAuth,我可以使用 _id 作为用户的 OAuth token 吗?我想这样做是因为它为数据库提供了清洁度和可索引性(例如,“tokens._id”=> oauth_token)。
检查 MongoDB _id 对象的结构,它们似乎是相当随机的,但我确实对恶意实体暴力猜测一个存在一些挥之不去的担忧。
最佳答案
简而言之,没有。 Mongo ObjectIds
很容易猜到。特别是在高负载下,这些通常是连续的数字,因为时间戳、机器和进程 ID 不会改变。如果你看 the structure of Objectid ,它们是由
a 4-byte timestamp,
a 3-byte machine identifier,
a 2-byte process id, and
a 3-byte counter, starting with a random value.
因此,它们几乎没有随机性。我经常在数据库中看到连续的 id,例如,如果某些 Controller 操作写入域对象,以及快速连续的日志条目。
如果时间戳可以猜到并且机器ID是可确定的(除非你有一个巨大的集群),那么就只剩下五个字节了。通过查看许多生成的 id,我可能可以将其减少到 50 个进程,因此有效熵在 28 位范围内。这仍然很难猜测,但对于访问 token 来说风险太大。
改用加密性强的伪随机数生成器并从中创建 token 。例如,在 .NET 中,RNGCryptoServiceProvider
允许创建任意长度的随机数据。
作为旁注,我建议在您的 OAuthTokens 周围添加一个额外的加密包装器,原因有两个:
a) 您希望能够快速确定无效 token 。一个有效的加密 shell 可能仍然包含一个无效的 token (一个被撤销或过期的授权),但你不必每次都对数据库进行暴力攻击。另外,客户端
b) 客户端可以反复请求 token 。虽然这不是必需的,但我所知道的几乎所有系统每次都会返回不同的 token (无论它们是否 self 验证)。通常,这是因为 token 本身的有效期有限。这与 OAuth 授权的有效期不同。
在数据库中,您真正要存储的是授权,即某个用户授予某个客户端的权限。如果删除此授权,则所有 token 都将无效。每次都插入一个新 token 非常不方便,因为用户必须删除所有 token 才能有效地删除应用程序授权。
关于mongodb - 使用 MongoDB 生成的 _ids 作为 "secret data"(例如,OAuth token ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15435530/