为 api 访问生成安全令牌
Posted
技术标签:
【中文标题】为 api 访问生成安全令牌【英文标题】:Generate a secure token for api access 【发布时间】:2015-11-16 03:27:07 【问题描述】:我需要生成一个安全令牌来访问 api。用户将进行身份验证,并且在成功的身份验证后,我将需要生成一个令牌。
重要提示:我确实需要能够随时撤销用户对 api 的访问权限。
选项 1:
我可以生成一个随机字符串并将其用作令牌。将令牌和用户存储在数据库中。当用户传递令牌时,我会检查数据库中的令牌,如果存在就去...
这使我能够通过删除用户令牌来撤销访问权限。如果他们尝试重新登录并且令牌消失了,他们将无法访问。我还可以根据时间使数据库中的令牌过期。
我正在使用 nodejs 并且看到了这个:
Secure random token in Node.js
require('crypto').randomBytes(48, function(ex, buf)
var token = buf.toString('hex');
);
这样真的安全吗,因为有人猜不到我生成的令牌?
选项 2:
使用类似 jwt 的东西。在 auth 上生成一个带有用户 ID 的 jwt。当用户在请求中传递该 jwt 时,我确保 jwt 有效,如果有效,则获取用户 ID 并准备就绪。这似乎更加安全,因为 jwt 可以防止篡改。
问题是撤销对 api 的访问。我可以将所有 jwt(直到它们过期)存储在数据库中,根据请求验证 jwt 并确保它在我的数据库中。如果我想撤销,我可以将它从数据库中删除。这里的缺点是我现在有验证 jwt 并查找它以确保它在我的数据库中的开销。
有没有使用 jwt 撤销访问的好方法?
【问题讨论】:
在数据库中存储 jwt 并检查它们的状态否定了这些令牌的主要优点 - 一旦经过身份验证,您就可以传递令牌,无需进一步查找。您可以设置一个较短的到期时间,但这可能会惹恼应该保持登录状态的用户。JWT 可能不是您想要的。 auth0.com/docs/refresh-token @NickJHoran 谢谢!您对主要优点是正确的,这就是为什么该解决方案看起来很糟糕。然而,无论我在哪里,似乎人们都在问如何“撤销”jwts。如果您出于安全原因需要这样做,或者如果用户在那里更改密码,则会发生这种情况。我看到你链接到刷新令牌。这是一个可能的答案吗? 这确实取决于您的设计要求,但刷新令牌可能对您有用。 【参考方案1】:这个问题可能会在答案中引起很多意见,因此最终取决于您和您的安全要求。
我喜欢的一个解决方案是按照您建议的方式生成随机字符,并在其中包含用户拥有的某些内容(例如电子邮件地址或 ID)。然后还包括一个时间戳以了解它何时生成。把这些东西合并成一个字符串(也许使用一些字符来分割部分)。所以你最终会得到类似的东西:
<random-string-of-characters>|<user-email-address>|<timestamp>
现在加密那个字符串,也许使用bcrypt 之类的东西,那个blob 最终就是你所说的“令牌”。它的内部用户不必了解它,他们只需要存储它并稍后访问它以将其发送到您的安全层进行验证。您可以通过解密并验证部分来验证它。
此解决方案可让您完全控制授予用户访问权限的方式。您可以继续将生成的字符存储在数据库中并随时撤消,或者查看时间戳以查看它们是否“超时”。
我想有很多解决方案,所以这只是一个:)
【讨论】:
是的,我在写这篇文章时试图避免意见答案,这很难做到。感谢您的回答。 Bcyrpt 似乎会增加一点安全性,但会牺牲计算时间。猜猜我只是不知道使用 bcyrpt 对于短暂的令牌是否过大。 是的,这取决于您希望它有多安全 :) 如果您不太关心安全性,您甚至可以生成一个 UUID 并将其用作令牌。有很多选择! bcrypt 不是单向算法吗?您只能将给定的哈希与组成它的部分进行比较并通过 bcrypt 运行它,它会告诉它是否匹配?就像bcrypt.compare(
$uuid|$email|$createdAt, hash, function(err, result) ...
这意味着您必须将 uuid 与创建日期一起存储,以便以后能够告诉令牌。因此,如果恶意攻击者获得了对数据库的访问权限,他可以重新创建使散列无用的令牌!
我认为您不必为令牌使用存储 uuid 和创建日期(尽管您可能仍会存储它们)。您不能只存储令牌并将其链接到数据库中的帐户吗?以上是关于为 api 访问生成安全令牌的主要内容,如果未能解决你的问题,请参考以下文章