【问题标题】:Where to store access tokens?在哪里存储访问令牌?
【发布时间】:2015-06-01 21:31:00
【问题描述】:

我正在构建一个 RESTful web api。一旦用户通过身份验证和授权,他们就会获得一个访问令牌,其中包含:

  • user_id
  • 时间戳
  • 权限

我的问题是,是否最好使用对称算法加密这些令牌并将其传递给客户端,或者只在我的session table 中传递一个指向用户会话的唯一哈希。所以基本上:

令牌存储在客户端 - 当服务器收到令牌时,它正在被解密并且所有数据都在内存中。

有关会话的数据存储在数据库中,客户端接收哈希 - 当服务器接收哈希时,会话数据正在数据库中查找并从那里获取。

哪种解决方案更适合处理数百万用户的大型服务?

【问题讨论】:

    标签: c# .net rest session asp.net-web-api


    【解决方案1】:

    从可扩展性的角度来看,最好生成一个包含信息的令牌,在服务器上对其进行签名,然后将其传递回客户端存储并随每个请求返回。通过在服务器上对其进行签名,您可以使其免受用户篡改数据的影响。唯一的要求是您庄园中的所有服务器都具有相同的密钥来签署和检查令牌上的签名。

    有一个执行此操作的标准,称为 JSON Web Tokens,它在几乎所有正在运行的框架中都有实现,包括 support in .NET from Microsoft

    【讨论】:

    • 如果我们不存储任何服务器端状态,我们无法在用户注销时使 JWT 失效。实际上我们的服务没有注销功能,这可能是一个安全问题,特别是如果我们将过期时间设置得太远。另一方面,如果我们将过期时间设置得太早,我们可能会遇到用户仍在登录但没有有效 JWT 的问题。这可能会导致尴尬的错误处理和用户工作流程问题。有没有办法解决这个问题?提供 api 方法“refresh_token”是个好主意吗?
    • 服务实际上变成了无会话的,因此从 API 的角度来看,“登录”或“注销”的概念确实不是正确的思考方式 -这是关于让用户相信他们就是他们所说的那个人。一旦存储了某种会话状态,扩展就变得更加困难,因为它必须由所有服务器共享。使用 API 方法刷新令牌没有问题。
    【解决方案2】:

    就我个人而言,我会将令牌寄回。但我不会依赖令牌来提供信息;而是我将其用作哈希以再次获取特定用户的信息。

    缓存应该能够解决任何性能问题。

    相对于您的两个选项,我会这样做的原因是:

    1. 如果令牌包含有关身份验证和授权的信息,则可以在客户端对其进行操作。有人需要的只是解密密钥。最好在更难操作的服务器上获取(并验证)这些信息。
    2. 会话总是会对性能产生影响,所以我建议避免它。此外,在开发网站本身时,使用 session 可能会鼓励一些“不良”做法(例如,在 session 中存储太多或所有内容,使用 session 来解决设计缺陷等)。

    【讨论】: