【问题标题】:If REST applications are supposed to be stateless, how do you manage sessions?如果 REST 应用程序应该是无状态的,那么您如何管理会话?
【发布时间】:2011-03-07 12:36:57
【问题描述】:

我需要澄清一下。我一直在阅读有关 REST 和构建 RESTful 应用程序的内容。根据维基百科,REST 本身被定义为Representational State Transfer。因此,我不明白每个人都在吐槽的所有这些无状态的 gobbledeygook

来自维基百科:

在任何特定时间,客户端都可以在 应用程序状态或“静止”。处于休息状态的客户端能够 与其用户交互,但不产生负载并且不消耗每个客户端 存储在一组服务器或网络上。

他们只是说不要使用会话/应用程序级数据存储吗???

我知道 REST 的一个目标是使 URI 访问保持一致且可用,例如,不是将分页请求隐藏在帖子中,而是使请求的页码成为 GET URI 的一部分。我感觉合理。但似乎只是说每个客户端数据(会话数据)都不应该存储在服务器端。

如果我有一个消息队列,并且我的用户想要阅读这些消息,但是当他阅读它们时,想要在他的会话期间阻止某些发件人消息通过,该怎么办?将其存储在服务器端的某个位置,并让服务器仅发送未被用户阻止的消息(或消息 ID)是否有意义?

每次我请求新的邮件列表时,我真的必须发送整个邮件发件人列表来阻止吗?与我相关的消息列表首先不会/不应该是公开可用的资源..

再次,只是试图理解这一点。有人澄清一下。


更新:

我发现了一个堆栈溢出问题,它的答案并没有完全让我明白: How to manage state in REST 这表示重要的客户端状态应该在每个请求上都被传输.... Ugg.. 似乎有很多开销...这是对的吗??

【问题讨论】:

  • @S.Lott:我不认为这是故意误导。我认为这是一种误解,因为术语混乱。
  • @只是我的正确意见:有趣的猜测。我自己都不敢相信这样的事情,因为“无状态”显然意味着 REST 协议本身是无状态的;它没有说明底层应用程序状态以及使用 PUT、POST 和 DELETE 请求对其进行更新。
  • @S.Lott :HTTP 协议本身是无状态的。从我们下面讨论的内容来看,REST 是关于如何在不让网络服务器处理会话状态的情况下构建应用程序的观点(与数据库等其他类型的状态相反)。我什至不认为 REST 协议,而是关于如何使用 HTTP 协议的观点。我以为你们澄清了,这是关于如何通过让客户端存储所有客户端特定的会话数据,并使 URI 访问尽可能幂等来构建应用程序以进行扩展,除非它们应该在哪里访问不是。也许不是... :(
  • “也许不是……”这是什么意思?你有新问题吗?随意搜索它。如果这里不存在,请询问。
  • 有没有人读过 Webber、Parastatidis 和 Robinson 的 ReST in Practice(或者看过他们的 restbucks 例子)?下面的答案是有道理的,但是 restbucks 示例中的咖啡订单肯定是关于客户的状态吗?订单数量与客户数量成正比。客户端状态和资源之间的界限在哪里?

标签: rest session-state


【解决方案1】:

基本解释是:

服务器上没有客户端会话状态。

无状态意味着服务器不会在服务器端存储任何关于客户端会话的状态。

客户端会话存储在客户端上。服务器是无状态的,这意味着每个服务器都可以随时为任何客户端提供服务,没有会话亲和性粘性会话。相关会话信息存储在客户端,并根据需要传递给服务器。

这并不排除 Web 服务器与之通信的其他服务维护有关诸如购物车之类的业务对象的状态,只是不排除有关客户端当前应用程序/会话状态的状态。

客户端的应用程序状态永远不应该存储在服务器上,而是从客户端传递到每个需要它的地方。

这就是REST中的ST的来源,State Transfer。您转移状态而不是让服务器存储它。 这是扩展到数百万并发用户的唯一方法。如果没有其他原因,因为数百万会话就是数百万会话。

会话管理的负载由所有客户端分摊,客户端存储其会话状态,服务器可以以无状态方式为多个数量级或更多客户端提供服务。

即使对于您认为需要成千上万个并发用户的服务,您仍然应该使您的服务无状态。几万还是几万,还有时间和空间成本。

无状态是 HTTP 协议和一般网络的设计方式,是一个整体上更简单的实现,您有一个单一的代码路径而不是一堆服务器端逻辑来维护一堆会话状态。

有一些非常基本的实现原则:

这些是原则而不是实现,您如何满足这些原则可能会有所不同。

综上所述,five key principles 是:

  1. 给每个“事物”一个 ID
  2. 将事物联系在一起
  3. 使用标准方法
  4. 具有多种表示形式的资源
  5. 无状态通信

REST dissertation 中没有任何关于身份验证或授权的内容。

因为验证一个 RESTful 请求和一个非 RESTful 请求没有什么不同。身份验证与 RESTful 讨论无关。

解释如何为您的特定需求创建无状态应用程序对于 StackOverflow 来说过于宽泛

实现与 REST 相关的身份验证和授权就更加过于宽泛了,各种实现方法在互联网上都有详细的解释。

寻求帮助/信息的评论将/应该被标记为 不再需要

【讨论】:

  • 这似乎是一个相当大胆的声明,它是扩展到数百万用户的唯一方法。为什么服务器端会话不能只是另一个服务?
  • @Zak:因为数百万次会话就是数百万次会话。关键是要避免所有这些会话管理的开销。
  • 经验不是胆量
  • 我的回答中没有任何内容暗示基于每个请求的数据库访问的解决方案,如果您认为是这样,那么您无法理解这种规模的身份验证和授权。身份验证可以隐含在状态中,您是否认为 facebook 对其 REST API 的每个请求都进行“数据库访问”?还是谷歌? 提示:没有
  • 所以,如果我将用户状态存储在分布式缓存中,比如 memcache,并且我所有的 web 服务器现在不需要存储任何状态,而是从 memcache 中获取状态,我可以认为这个应用程序是无状态的?
【解决方案2】:

无状态意味着每个 HTTP 请求都是在完全隔离的情况下发生的。当客户端发出 HTTP 请求时,它包含服务器完成该请求所需的所有信息。服务器从不依赖来自先前请求的信息。如果该信息很重要,则客户端将不得不在后续请求中再次发送。无状态也带来了新的功能。在负载平衡的服务器之间分发无状态应用程序更容易。无状态应用也很容易缓存。

实际上有两种状态。位于客户端的应用程序状态和位于服务器上的资源状态。

Web 服务只需要在您实际发出请求时关心您的应用程序状态。其余时间,它甚至不知道你的存在。这意味着每当客户端发出请求时,它必须包含服务器处理它所需的所有应用程序状态。

每个客户端的资源状态都是相同的,它的正确位置是在服务器上。当您将图片上传到服务器时,您会创建一个新资源:新图片有自己的 URI,并且可以成为未来请求的目标。您可以通过 HTTP 获取、修改和删除此资源。

希望这有助于区分无状态和各种状态的含义。

【讨论】:

  • 这是否意味着每次发送请求时客户端都应发送其用户/密码以进行身份​​验证?因为我猜想存储一个会话,即使它在所有服务器之间的共享 no-sql 数据库上,也不是无状态的,或者是吗?
  • @CarlosNavarroAstiasarán 有多种技术可用于处理无状态身份验证。以 Google JWT 为例。
  • @geoidesic:“因为 JSON Web 令牌是无状态的,所以如果不存储服务器状态就无法使它们失效,从而破坏了无状态令牌的优势。” WIkipedia
  • @AndrewTFinnell:如果您必须将批准的 ID 存储在服务器上,那么它必须存储在所有可以处理 REST 登录的潜在服务器上,这可能涉及跨平台的大量服务器状态大规模并行网络服务器架构。
  • 此答案中的句子已从“Leonard Richardson 和 Sam Ruby 的 RESTful Web Design”一书中逐字复制。如果您在回答中给出了参考,那就太好了。请阅读本文以了解 meta.stackoverflow.com/a/299918/608170 Stackoverflow 对剽窃的看法
【解决方案3】:

他们只是说不要使用会话/应用程序级别的数据存储吗???

没有。他们并没有以微不足道的方式这么说。

他们说不要定义“会话”。不要登录。不要注销。随请求提供凭据。每个请求都是独立的。

您仍然有数据存储。您仍然具有身份验证和授权。您只是不会浪费时间建立会话和维护会话状态。

关键在于,每个请求 (a) 完全独立,并且 (b) 无需任何实际工作即可轻松地将其分流到一个巨大的并行服务器群。 Apache 或 Squid 可以盲目且成功地传递 RESTful 请求。

如果我有一个消息队列,并且我的用户想要阅读这些消息,但当他阅读它们时,想在他的会话期间阻止某些发件人消息通过,该怎么办?

如果用户想要一个过滤器,那么只需在每个请求上提供过滤器。

... 让服务器只发送未被用户阻止的消息(或消息 ID)不是很有意义吗?

是的。在 RESTful URI 请求中提供过滤器。

每次我请求新的邮件列表时,我真的必须发送整个邮件发件人列表来阻止吗?

是的。这个“要阻止的消息发件人列表”有多大? PK的简短列表?

GET 请求可能非常大。如有必要,您可以尝试 POST 请求,即使它听起来像是一种查询。

【讨论】:

  • “不要登录。不要注销。在请求中提供凭据。”我总是在关于如何在 REST API 中保持无状态的问题中看到这样的回答,而没有任何关于应该在哪里/如何将这些凭据存储在客户端上的详细信息。我们当然不应该将用户名和密码存储在本地存储中!
  • @BeniRose 我们可以不将令牌存储在本地存储中并在请求中使用该令牌来唯一标识用户吗?
  • 据我了解,Localstorage 存在很多安全问题。但客户端会话还有许多其他问题,例如使令牌无效、用户注销等。
  • 你使用的是有签名的JWT,签名验证速度很快,所以你可以检查那个状态的有效性。
【解决方案4】:

您说的完全正确,支持与服务器完全无状态的交互确实给客户端增加了额外的负担。但是,如果您考虑扩展应用程序,则客户端的计算能力与客户端的数量成正比。因此,扩展到大量客户端更为可行。

一旦您将一点点责任交给服务器来管理与特定客户端交互相关的一些信息,这种负担就会迅速增长到消耗服务器。

这是一种权衡。

【讨论】:

    【解决方案5】:

    用户应用状态管理历史视图

    传统意义上的会话将用户的状态保存在服务器内部的应用程序中。这可能是流程中的当前页面,也可能是之前输入但尚未持久化到主数据库的页面。

    这种需求的原因是客户端缺乏标准来有效地维护状态,而无需制作特定于客户端(即特定于浏览器)的应用程序或插件。

    HTML5 和 XML 标头请求随着时间的推移标准化了在客户端(即浏览器)端以标准方式存储复杂数据(包括 应用程序状态)的概念,而无需在服务器之间来回切换。

    REST 服务的一般用法

    当需要执行事务或需要检索数据时,通常会调用 REST 服务。

    REST 服务旨在由客户端应用程序调用,而不是由最终用户直接调用。

    认证

    对于服务器的任何请求,请求的一部分应包含授权令牌。它的实现方式是特定于应用程序的,但通常是BASICCERTIFICATE 形式的身份验证。

    REST 服务不使用基于表单的身份验证。但是,如上所述,REST 服务并不是由用户调用,而是由应用程序调用。应用程序需要管理获取身份验证令牌。在我的例子中,我使用带有 JASPIC with OAuth 2.0 to connect to Google for authentication 的 cookie 和简单的 HTTP 身份验证来进行自动化测试。我还使用HTTP Header authentication via JASPIC 进行本地测试(尽管可以在 SiteMinder 中执行相同的方法)

    根据这些示例,身份验证在客户端进行管理(尽管 SiteMinder 或 Google 会将身份验证会话存储在其端),对此状态无能为力,但它不是 REST 服务的一部分申请。

    检索请求

    REST 中的检索请求是 GET 操作,其中请求特定资源并且可缓存。不需要服务器会话,因为请求具有检索数据所需的一切:身份验证和 URI。

    交易脚本

    如上所述,客户端应用程序本身调用 REST 服务以及它在客户端管理的身份验证。

    这对于 REST 服务意味着 [如果正确完成] 是向 REST 服务器发出单个请求,该请求将包含单个用户操作所需的所有内容,该操作在单个事务中执行所需的所有操作,Transaction Script就是所谓的模式。

    这通常通过POST 请求完成,但也可以使用其他如PUT

    许多人为设计的 REST 示例(我自己做了这个)试图尽可能多地遵循 HTTP 协议中定义的内容,在经历了这些之后,我决定更加务实并将其留给 GET and POST onlyPOST 方法甚至不必实现 POST-REDIRECT-GET 模式。

    尽管如此,正如我上面提到的,客户端应用程序将是调用服务的应用程序,它只会在需要时(不是每次)调用带有所有数据的 POST 请求。这可以防止对服务器的持续请求。

    轮询

    虽然 REST 也可以用于轮询,但我不会推荐它,除非因为浏览器兼容性而必须使用它。为此,我将使用我设计了API contract 的 WebSockets。旧版浏览器的另一个替代方案是 CometD。

    【讨论】:

      【解决方案6】:

      REST 非常抽象。有一些好的、简单的、真实的例子会很有帮助。

      以所有主要的社交媒体应用程序为例——Tumblr、Instagram、Facebook 和 Twitter。它们都有一个永远滚动的视图,您向下滚动的越远,您看到的内容就越多,而且时间越长。但是,我们都经历过您失去滚动到的位置的那一刻,该应用程序会将您重置回顶部。就像你退出应用程序,然后当你重新打开它时,你又回到了顶部。

      之所以如此,是因为服务器没有存储你的会话状态。可悲的是,您的滚动位置只是存储在客户端的 RAM 中。

      幸运的是,您在重新连接时不必重新登录,但这只是因为您的客户端也存储的登录证书尚未过期。删除并重新安装该应用程序,您将不得不重新登录,因为服务器没有将您的 IP 地址与您的会话相关联。

      您在服务器上没有登录会话,因为它们遵守 REST。


      现在,上述示例根本不涉及网络浏览器,但在后端,应用程序通过 HTTPS 与其主机服务器进行通信。我的观点是 REST 不必涉及 cookie 和浏览器等。有多种存储客户端会话状态的方法。

      但是让我们先谈谈网络浏览器,因为这带来了 REST 的另一个主要优势,这里没有人在谈论。

      如果服务器试图存储会话状态,它应该如何识别每个单独的客户端?

      它无法使用他们的 IP 地址,因为许多人可能在共享路由器上使用相同的地址。那怎么办?

      它不能使用 MAC 地址有很多原因,其中最重要的原因是您可以在不同的浏览器和应用程序上同时登录多个不同的 Facebook 帐户。一种浏览器可以很容易地伪装成另一种浏览器,而 MAC 地址同样容易被欺骗。

      如果服务器必须存储一些客户端状态来识别您,它必须将其存储在 RAM 中,而不仅仅是处理您的请求所花费的时间,否则它必须缓存该数据。服务器的 RAM 和缓存数量有限,更不用说处理器速度了。服务器端状态以指数方式添加到所有三个中。另外,如果服务器要存储有关您会话的任何状态,那么它必须为您当前登录的每个浏览器和应用程序以及您使用的每个不同设备单独存储它。


      所以...我希望您现在明白为什么 REST 对于可扩展性如此重要。 我希望你能开始明白为什么服务器端会话状态对服务器可扩展性的影响就像焊接铁砧对汽车加速的影响一样。


      人们感到困惑的地方是认为“状态”是指存储在数据库中的信息。不,它是指在您使用服务器时需要在服务器内存中的任何信息。

      【讨论】:

        【解决方案7】:

        没有勺子。

        不要将无状态视为“一次又一次地将所有您的东西发送到服务器”。没门。总会有状态——数据库本身毕竟是一种状态,你是注册用户,所以任何一组客户端信息在没有服务器端的情况下都是无效的。从技术上讲,您永远不会真正无国籍。

        登录辩论

          不保持会话并每次都登录意味着什么?

          有些意思是“每次都发送密码”,这很愚蠢。有人说“当然不是,而是发送一个 token” - 你瞧,PHP 会话几乎就是这样做的。它发送一个 session id,它是一种 token,它可以帮助您访问您的个人资料,而无需每次都重新发送 u/pw。它也非常可靠且经过良好测试。是的,方便,这可能会变成一个缺点,请参阅下一段。

        减少占用空间

          相反,您应该做的 以及真正有意义的做法是将您的网络服务器占用空间减至最低。像 PHP 这样的语言使得在会话存储中填充所有内容变得非常容易——但是会话有一个价格标签。如果您有多个网络服务器,它们需要共享会话信息,因为它们也共享负载 - 它们中的任何一个都可能必须为下一个请求提供服务。

          共享存储是必须的。服务器至少需要知道是否有人登录。 (如果每次需要决定时都打扰数据库,那您实际上就注定要失败。)共享存储需要比数据库快得多。这带来了诱惑:好吧,我有一个非常快的存储空间,为什么不在那里做所有事情呢? - 这就是事情变得糟糕的地方。

        所以您的意思是,将会话存储保持在最低限度?

          再次,这是你的决定。您可以出于性能原因将内容存储在那里(数据库几乎总是比 Redis 慢),您可以冗余地存储信息,实现自己的缓存,无论如何 - 请记住,如果您存储大量垃圾,Web 服务器将有更大的负载在他们。此外,如果它们在重载下破裂(它们会),您将丢失有价值的信息;使用 REST 的思维方式,在这种情况下发生的所有事情都是客户端再次发送相同的(!)请求,这次它得到了服务。

        那该怎么做呢?

          这里没有万能的解决方案。我会说选择一定程度的无国籍状态并继续下去。会话可能会被一些人喜欢而被其他人讨厌,但他们不会去任何地方。对于每个请求,发送尽可能多的信息,也许更多;但不要将无状态解释为没有会话,也不要每次都登录。 不知何故服务器必须知道是你; PHP 会话 ID 是一种好方法,手动生成的令牌是另一种方法。

          思考和决定——不要让设计趋势替你思考。

        【讨论】:

        • “三思而后行,不要让设计趋势替你思考。”不幸的是,现在愚蠢地跟随潮流变得非常普遍。有时阅读 SO,您会因为趋势而得到所有相同的答案。
        • @dkellner 我不明白那部分:“服务器至少需要知道某人是否登录。(如果每次需要决定时都打扰数据库,那么你就是几乎注定要失败。)“。假设您使用 PHP 将会话数据存储在数据库中。为什么查询数据库登录错误(注定是一个强词)反正会有许多后续的数据库请求来获取完整的用户数据和其他东西,基于 PHP 会话 ID?换言之,DB 查询在任何情况下都是不可避免的。此外,如果您没有收到 PHP 会话 ID,则您知道该用户未经身份验证,无需查询。
        • 正确。另外:我尝试自己实现诸如登录服务器之类的东西——这样我就知道为什么我不想再这样做了。使用标准化的模式、程序和框架。身份验证和授权过程非常技术性。但是那些还没有被持久化的“会话”呢?好吧-从技术上讲,您仍然可以保留它们,但只要将它们标记为transient,例如合同实际上并没有被“保存”或打印或其他东西。另外:我想通过服务而不是通过公共数据库保持通信(也看到了这个)。
        • 为什么这里没有人提到 JWT 令牌之类的?这些令牌包含一个人的身份、他们的声明(即权限)、到期时间等等。使用令牌,您实际上不需要进行数据库查找,也不需要共享状态来验证调用者。
        • @dkellner 通常你不会给你的客户这个“钥匙”。相反,他们的客户端针对颁发此令牌的身份提供者进行身份验证,并且这些令牌通常在一定时间后过期。服务器需要做的一件重要事情是验证令牌,其中包括根据颁发者的证书检查签名。
        【解决方案8】:

        我发现这里的基本问题是将 SessionState 混为一谈。虽然 REST 规定您不应将 State 存储在服务器上,但没有什么能阻止您存储用户 Session

        管理服务器上的状态意味着您的服务器确切地知道客户端在做什么(他们在应用程序的哪个部分查看哪个页面)。这是你不应该做的。

        我同意其他人的观点,即您应该将会话存储保持在最小大小;虽然这是常识,但它实际上也取决于应用程序。 因此,简而言之,您仍然可以与缓存数据保持会话,以在服务器上以较少的负载处理请求,并通过提供临时身份验证/访问令牌供客户端使用来管理身份验证。每当会话/令牌过期时,生成一个新的并要求客户端使用它。

        有人可能会争辩说客户端应该更好地生成令牌。我说它是双向的,它取决于应用程序,以及谁将使用 API。

        在服务器上保留一些敏感的会话数据应该是正确的做法。您不能相信客户会保留他们的购物车(例如)包含名为“isFreeGift”的字段。此类信息应保存在服务器上。

        Santanu Dey 在他的回答中提供的视频链接很有帮助。如果你还没有,请观看它。

        只是一个旁注:似乎已经给出的所有答案似乎都忽略了某些操作可能导致服务器负载过重的事实。这与功耗、硬件消耗和成本相关(对于按 CPU 周期租用的服务器)。优秀的开发人员不应该偷懒优化他们的应用程序,即使可以在租用的服务器上的现代 CPU 上非常快速地完成操作,而无需支付电费和维护费用。

        虽然这个问题是几年前的问题,但我希望我的回答仍然有帮助。

        【讨论】:

        • 我大体上同意这种观点,但最近有一种趋势是声称即使是会话标识符也不应该存储在服务器上。我还没有找到替代解决方案是什么,JWT 很受吹捧,但也有一些陷阱:cryto.net/~joepie91/blog/2016/06/19/…
        【解决方案9】:

        无状态意味着服务的状态不会在后续请求和响应之间持续存在。每个请求都带有自己的用户凭据,并单独进行身份验证。但是在有状态的情况下,每个请求都是从任何先前的请求中得知的。所有有状态的请求都是面向会话的,即每个请求都需要知道并保留在先前请求中所做的更改。

        银行应用程序是有状态应用程序的一个示例。用户首次登录然后进行交易并注销。如果注销后用户尝试进行交易,他将无法这样做。

        是的,http 协议本质上是一个无状态协议,但为了使其有状态,我们使用了 HTTP cookie。因此,默认情况下是 SOAP。但它也可以是有状态的,这取决于您使用的框架。

        HTTP 是无状态的,但我们仍然可以通过使用不同的会话跟踪机制在我们的 java 应用程序中维护会话。

        是的,我们也可以在 web 服务中维护会话,无论是 REST 还是 SOAP。可以使用任何第三方库实现,也可以自己实现。

        取自http://gopaldas.org/webservices/soap/webservice-is-stateful-or-stateless-rest-soap

        【讨论】:

          【解决方案10】:

          看看这个演示文稿。

          http://youtu.be/MRxTP-rQ-S8

          根据这种模式——在真正需要的时候创建临时的 restful 资源来管理状态。避免明确的会话。

          【讨论】:

          【解决方案11】:

          无状态与有状态的主要区别在于每次都将数据传回服务器。在无状态的情况下,客户端必须提供所有信息,因此可能需要在每个请求中传递大量参数。在有状态的情况下,客户端将这些参数传递一次,然后由服务器维护,直到客户端再次修改它们。

          IMO,API 应该是无状态的,这样可以快速扩展。

          【讨论】:

            【解决方案12】:

            您必须在客户端管理客户端会话。这意味着您必须在每个请求中发送身份验证数据,并且您可能(但不一定)在服务器上有一个内存缓存,它将身份验证数据与身份、权限等用户信息配对......

            这个 REST statelessness constraint 非常重要。如果不应用此约束,您的服务器端应用程序将无法很好地 scale,因为维护每个单独的客户端会话将是它的 Achilles' heel

            【讨论】:

            • 如果您在每个请求中发送身份验证数据,您在客户端的何处/如何存储凭据,以便用户不必在每次请求时重新输入?
            【解决方案13】:

            当您开发 RESTful 服务时,您需要对用户进行身份验证才能登录。一个可能的选择是在您每次打算执行用户操作时发送用户名和密码。在这种情况下,服务器根本不会存储会话数据。

            另一种选择是在服务器上生成一个 session-id 并将其发送到客户端,这样客户端就可以将 session-id 发送到服务器并对其进行身份验证。这比每次发送用户名和密码要安全得多,因为如果有人掌握了该数据,那么他/她可以冒充用户,直到用户名和密码被更改。您可能会说即使会话 id 也可能被盗,在这种情况下用户将被冒充,您是对的。但是,在这种情况下,只有在会话 ID 有效时才能模拟用户。

            如果 RESTful API 需要用户名和密码来更改用户名和密码,那么即使有人使用会话 ID 冒充用户,黑客也无法锁定真实用户。

            可以通过单向锁定(加密)识别用户的东西并将时间添加到会话 ID 来生成会话 ID,这样就可以定义会话的到期时间。

            服务器可能会也可能不会存储会话 ID。当然,如果服务器存储会话 id,那么它将违反问题中定义的标准。但是,重要的是确保可以为给定用户验证会话 ID,这不需要存储会话 ID。想象一种方式,您对电子邮件、用户 ID 和一些特定于用户的私人数据(如最喜欢的颜色)进行单向加密,这将是第一级,并以某种方式将用户名日期添​​加到加密字符串并应用两个-方式加密。因此,当接收到会话 id 时,可以对第二级进行解密,以便能够确定用户声称是哪个用户名以及会话时间是否正确。如果这是有效的,那么可以通过再次进行该加密并检查它是否与字符串匹配来验证第一级加密。您无需存储会话数据即可实现这一目标。

            【讨论】:

            • 这是有道理的
            【解决方案14】:

            整个概念是不同的...如果您尝试实现 RESTFul 协议,则不需要管理会话。在这种情况下,最好对每个请求进行身份验证(而在性能方面需要额外的成本 - 散列密码就是一个很好的例子。没什么大不了的......)。如果您使用会话 - 如何在多个服务器之间分配负载?我敢打赌 RESTFul 协议旨在消除任何会话——你并不真的需要它们……这就是为什么它被称为“无状态”的原因。仅当您在提出请求后无法在客户端存储除 Cookie 之外的任何内容时(以旧的、不支持 Javascript/HTML5 的浏览器为例),才需要会话。在“全功能” RESTFul 客户端的情况下,将base64(login:password) 存储在客户端(在内存中)通常是安全的,直到仍然加载应用程序 - 应用程序用于访问唯一的主机并且 cookie 不会受到损害由第三方脚本...

            我强烈建议禁用 RESTFul 服务的 cookie 身份验证...查看 Basic/Digest Auth - 这对于基于 RESTFul 的服务应该足够了。

            【讨论】:

            • 什么是a client side (in memory) 以及如何在客户端安全地保存base64(login:password)
            • 没有任何东西被定义为“完全安全”。但是,您可以考虑使用 OAuth2 提供比为 API 请求保存 base64 字符串(基本身份验证)更好的安全性,如果您坚持使用基本身份验证,则可以使用 HTTPS 以获得更好的安全性。
            • RN Kushwaha,当他们告诉您停止在服务器上存储会话并将其存储在客户端时,似乎没人想回答这个问题。
            【解决方案15】:

            REST 是无状态的,不会在请求之间维护任何状态。客户端 cookie / 标头设置为维护用户状态,如身份验证。假设客户端用户名/密码通过第三方身份验证机制进行验证 - 二级 OTP 生成等。一旦用户通过身份验证 - 标头 /cookies 进入休息服务端点暴露,我们可以假设用户为身份验证,因为用户带有有效的标头/cookies .现在,用户的某些信息(如 IP)要么保存在缓存中,然后如果请求来自列出的资源的相同 IP(mac 地址),则允许用户。并且缓存会保留一段时间,一旦时间流逝,这些特定时间就会失效。因此,可以使用缓存或 DB 条目来保存请求的黑白信息。

            【讨论】:

              【解决方案16】:

              这里的无状态意味着请求的状态或元数据不在服务器端维护。通过在服务器上维护每个请求或用户的状态,会导致性能瓶颈。只是请求服务器提供所需的属性来执行任何特定的操作。

              为了管理会话或为用户提供定制体验,它需要维护一些元数据或用户可能的用户偏好状态、过去的请求历史记录。这可以通过维护 cookie、隐藏属性或会话对象来完成。

              这可以维护或跟踪用户在应用程序中的状态。

              希望这会有所帮助!

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2012-07-03
                • 2018-09-04
                • 1970-01-01
                • 2010-09-10
                • 2017-01-10
                • 2010-10-04
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多