RESTful 身份验证 - 在高负载下导致性能不佳?

对于 RESTful Web 服务,我们说服务器不应该存储任何状态。现在,对于每个请求,“用户”都必须经过身份验证,并且必须对他/她希望执行的操作进行授权。

现在,每个请求都将包含该用户的授权数据。以下是我的困惑:

假设主页上有登录名和密码字段。用户输入用户名/密码,该用户名/密码被发送回服务器,用户验证,然后返回“一些令牌”。现在,此令牌在每次请求时都会发送到服务器。问题:

  • 后端数据库是否需要有一个单独的表来存储这些按用户名编制索引的令牌?
  • 假设令牌存储在数据库中,则每个请求都需要进行数据库调用。这难道不会使数据库服务器在高负载时期成为瓶颈吗?
  • 如果令牌没有真正存储在数据库中,那么存储它的最佳“宁静”位置是什么?
  • 拥有会话可能不是安宁的,但是我看不到如何安宁的身份验证/授权扩展(w.r.t.上述几点)?
  • 如果它不是令牌,那么用户名/密码是否需要来回发送?(听起来像是个坏主意:)

我可能误解了RESTful身份验证/授权的概念。但是,对于每个http请求,“服务”都需要前往数据库以验证凭据,这真的是这种情况吗?有没有一些东西可以缩短这个过程,同时仍然忠于宁静的原则?我可以想到有一个缓存来存储详细信息,并且在服务器重新启动的情况下,它只是使数据库之旅。这只是一个性能优势,可能会使系统复杂化(也许值得,不知道)。这是唯一的解决方案吗?

那么从REST的理论/概念角度来看(不是必需的实现),如何处理这个问题(如果它是一个问题)?在你的专业经验中,你是如何处理这个问题的,这种方法有多Restful?

我们正在开发一个Restlet + J2EE + MySQL Restful Web服务,我弹出了这个问题,但没有令人满意的答案(Google,Stackoverflow等),我知道HTTP的基本和摘要授权,但我不熟悉上述解释的存储/检索的内部结构。


答案 1

REST的精神是无国籍。这并不意味着服务不能持久化客户端状态,但在实践中,这确实意味着服务器在内存中保存的客户端状态通常是一件坏事。

与其将身份验证数据保存在内存中,或者每次都转到数据库进行验证,不如在内存中保留一个用于加密/解密用户信息的函数(即代码)。这是一种技术,也是由以下人员建议的:

我应该在Cookie中存储什么才能在用户登录期间实现“记住我”

因此,例如,您将执行以下操作:

  1. 当客户端首次联系服务时,它没有 Cookie。
  2. 您发出包含用户信息的cookie,并使用您的函数对其进行“签名”(运行代码的所有服务器都可以这样做)
  3. 当客户端再次联系服务时,您检查它是否有cookie;如果没有,请重复(2)。
  4. 但是,如果它确实具有 cookie,则尝试解密(再次使用在基础结构中复制的单个函数)并验证是否可以解包和消化该用户 ID 信息。
  5. 这将验证用户并为您提供身份信息,所有这些都不会超出必要的次数进入DB。而且它是RESTful的。

请记住,我描述的这个“函数”并不是一件新鲜事 - 它是一个标准的安全哈希,而是一个基于只有您的集合服务器知道的唯一私钥的哈希。您可以根据需要轮换此类密钥等。


答案 2

您只需在登录时验证凭据(例如用户名/密码)。当用户成功登录时,您向他们发送一个包含无法猜测的“会话ID”的cookie。此会话 ID 将成为令牌,允许在检查凭据后进一步访问。服务器应用程序通过在某个内存中数据结构中查找令牌来验证令牌。令牌在一些合理的时间后过期,以防止内存耗尽。如果用户显式注销(按“注销”按钮),则会从内存中存储中显式删除令牌。

在发送和接收令牌时使用https非常重要 - 否则嗅探令牌会允许黑客“劫持会话”。换句话说,对从登录到注销的整个应用程序工作流使用 https。


推荐