如果 REST 应用程序应该是无状态的,那么如何管理会话?

发布于 2024-09-07 07:04:16 字数 852 浏览 1 评论 0原文

我需要一些澄清。我一直在阅读有关 REST 的内容,并构建 RESTful 应用程序。根据维基百科,REST 本身被定义为“表述性状态转移”。因此,我不明白每个人都在吐槽的所有这些无状态的官样文章

来自维基百科:

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

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

我知道 REST 的目标之一是使 URI 访问一致且可用,例如,不是将分页请求隐藏在帖子内,而是使请求的页码成为 GET URI 的一部分。对我来说很有意义。但似乎说不应该将每个客户端数据(会话数据)存储在服务器端似乎有点过分了。

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

每次我请求新的消息列表时,我真的必须发送整个消息发件人列表才能阻止吗?与我相关的消息列表一开始就不会/不应该成为公开可用的资源。

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


更新:

我发现了一个堆栈溢出问题,其答案并不能完全让我明白: 如何在 REST 中管理状态 这表明重要的客户端状态应该在每个请求上都被传输......呃..似乎有很多开销......这是对的吗?

I'm in need of some clarification. I've been reading about REST, and building RESTful applications. According to wikipedia, REST itself is defined to be Representational State Transfer. I therefore don't understand all this stateless gobbledeygook that everyone keeps spewing.

From wikipedia:

At any particular time, a client can either be in transition between
application states or "at rest". A client in a rest state is able to
interact with its user, but creates no load and consumes no per-client
storage on the set of servers or on the network.

Are they just saying don't use session/application level data store???

I get that one goal of REST is to make URI access consistent and available, for instance, instead of hiding paging requests inside posts, making the page number of a request a part of the GET URI. Makes sense to me. But it seems like it is just going overboard saying that no per client data (session data) should ever be stored server side.

What if I had a queue of messages, and my user wanted to read the messages, but as he read them, wanted to block certain senders messages coming through for the duration of his session? Wouldn't it make sense to store this in a place on the server side, and have the server only send messages (or message ID's) that were not blocked by the user?

Do I really have to send the entire list of message senders to block each time I request the new message list? The message list pertinent to me wouldn't/shouldn't even be a publicly available resource in the first place..

Again, just trying to understand this. Someone please clarify.


Update:

I have found a stack overflow question that has an answer that doesn't quite get me all the way there:
How to manage state in REST
which says that the client state that is important should all be transferred on every request.... Ugg.. seems like a lot of overhead... Is this right??

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

情栀口红 2024-09-14 07:04:16

根本的解释是:

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

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

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

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

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

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

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

即使对于您认为仅需要数十万个并发用户的服务,您仍然应该使您的服务无状态。几万仍然是几万,并且会产生与之相关的时间和空间成本。

无状态是 HTTP 协议和 Web 的总体设计运行方式,是一种整体上更简单的实现,您可以使用单个代码路径而不是一堆服务器端逻辑来维护一堆会话状态。

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

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

总之,五个关键原则是:

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

REST 中没有任何有关身份验证或授权的内容 论文

因为验证 RESTful 请求与非 RE​​STful 请求没有什么不同。身份验证与 RESTful 讨论无关。

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

实现与 REST 相关的身份验证和授权甚至更加过于宽泛,并且一般在互联网上都非常详细地解释了各种实现方法。

寻求有关此意愿的帮助/信息的评论/应该被标记为
不再需要

The fundamental explanation is:

No client session state on the server.

By stateless it means that the server does not store any state about the client session on the server side.

The client session is stored on the client. The server is stateless means that every server can service any client at any time, there is no session affinity or sticky sessions. The relevant session information is stored on the client and passed to the server as needed.

That does not preclude other services that the web server talks to from maintaining state about business objects such as shopping carts, just not about the client's current application/session state.

The client's application state should never be stored on the server, but passed around from the client to every place that needs it.

That is where the ST in REST comes from, State Transfer. You transfer the state around instead of having the server store it. This is the only way to scale to millions of concurrent users. If for no other reason than because millions of sessions is millions of sessions.

The load of session management is amortized across all the clients, the clients store their session state and the servers can service many orders of magnitude or more clients in a stateless fashion.

Even for a service that you think will only need in the 10's of thousands of concurrent users, you still should make your service stateless. Tens of thousands is still tens of thousands and there will be time and space cost associated with it.

Stateless is how the HTTP protocol and the web in general was designed to operate and is an overall simpler implementation and you have a single code path instead of a bunch of server side logic to maintain a bunch of session state.

There are some very basic implementation principles:

These are principles not implementations, how you meet these principles may vary.

In summary, the five key principles are:

  1. Give every “thing” an ID
  2. Link things together
  3. Use standard methods
  4. Resources with multiple representations
  5. Communicate statelessly

There is nothing about authentication or authorization in the REST dissertation.

Because there is nothing different from authenticating a request that is RESTful from one that is not. Authentication is irrelevant to the RESTful discussion.

Explaining how to create a stateless application for your particular requirements, is too-broad for StackOverflow.

Implementing Authentication and Authorization as it pertains to REST is even more so too-broad and various approaches to implementations are explained in great detail on the internet in general.

Comments asking for help/info on this will/should just be flagged as
No Longer Needed
.

秉烛思 2024-09-14 07:04:16

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

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

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

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

Statelessness means that every HTTP request happens in complete isolation. When the client makes an HTTP request, it includes all the information necessary for the server to fulfill that request. The server never relies on information from previous requests. If that information was important, the client would have to send it again in subsequent request. Statelessness also brings new features. It’s easier to distribute a stateless application across load-balanced servers. A stateless application is also easy to cache.

There are actually two kinds of state. Application State that lives on the client and Resource State that lives on the server.

A web service only needs to care about your application state when you’re actually making a request. The rest of the time, it doesn’t even know you exist. This means that whenever a client makes a request, it must include all the application states the server will need to process it.

Resource state is the same for every client, and its proper place is on the server. When you upload a picture to a server, you create a new resource: the new picture has its own URI and can be the target of future requests. You can fetch, modify, and delete this resource through HTTP.

梦在夏天 2024-09-14 07:04:16

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

不,他们并不是在以微不足道的方式这么说。

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

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

关键是每个请求(a)完全独立,并且(b)可以轻松地分配给一个巨大的并行服务器场,而无需任何实际工作。 Apache 或 Squid 可以盲目且成功地传递 RESTful 请求。

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

如果用户想要过滤器,则只需在每个请求上提供过滤器即可。

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

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

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

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

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

Are they just saying don't use session/application level data store???

No. They aren't saying that in a trivial way.

They're saying do not define a "session". Don't login. Don't logout. Provide credentials with the request. Each request stands alone.

You still have data stores. You still have authentication and authorization. You just don't waste time establishing sessions and maintaining session state.

The point is that each request (a) stands completely alone and (b) can be trivially farmed out to a giant parallel server farm without any actual work. Apache or Squid can pass RESTful requests around blindly and successfully.

What if I had a queue of messages, and my user wanted to read the messages, but as he read them, wanted to block certain senders messages coming through for the duration of his session?

If the user wants a filter, then simply provide the filter on each request.

Wouldn't it make sense to ... have the server only send messages (or message ID's) that were not blocked by the user?

Yes. Provide the filter in the RESTful URI request.

Do I really have to send the entire list of message senders to block each time I request the new message list?

Yes. How big can this "list of message senders to block" be? A short list of PK's?

A GET request can be very large. If necessary, you can try a POST request even though it sounds like a kind of query.

自由范儿 2024-09-14 07:04:16

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

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

这是一个权衡。

You are absolutely right, supporting completely stateless interactions with the server does put an additional burden on the client. However, if you consider scaling an application, the computation power of the clients is directly proportional to the number of clients. Therefore scaling to high numbers of clients is much more feasible.

As soon as you put a tiny bit of responsibility on the server to manage some information related to a specific client's interactions, that burden can quickly grow to consume the server.

It's a trade off.

哆兒滾 2024-09-14 07:04:16

用户应用程序状态管理的历史视图

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

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

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

REST 服务的一般用法

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

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

身份验证

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

REST 服务不使用基于表单的身份验证。然而,如上所述,REST 服务并不是由用户调用,而是由应用程序调用。应用程序需要管理获取身份验证令牌。就我而言,我使用 cookie 和 JASPIC 和 OAuth 2.0 连接到Google 进行身份验证,并使用简单的 HTTP 身份验证进行自动化测试。我还使用了 通过 JASPIC 进行 HTTP 标头身份验证对于本地测试(尽管可以在 SiteMinder 中执行相同的方法)

根据这些示例,身份验证是在客户端管理的(尽管 SiteMinder 或 Google 会在其端存储身份验证会话),但无能为力关于该状态,但它不是 REST 服务应用程序的一部分。

检索请求

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

事务脚本

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

对于 REST 服务来说,[如果正确完成]意味着向 REST 服务器发出单个请求将包含单个用户操作所需的所有内容,该操作完成单个事务中所需的所有操作,即 事务脚本 是该模式的名称。

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

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

不管怎样,正如我上面所指出的,客户端应用程序将是调用该服务的应用程序,并且它只会在需要时(不是每次)使用所有数据调用 POST 请求。这可以防止对服务器的持续请求。

轮询

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

Historical view of user application state management

Sessions in the traditional sense keep the user's state in the application inside the server. This may be the current page in a flow or what has been previously entered but not persisted to the main database yet.

The reason for this need was the lack of standards on the client side to effectively maintain the state without making client specific (i.e. browser specific) applications or plug-ins.

HTML5 and XML Header Request has over time standardized the notion of storing complex data including application state in standard way on the client (i.e. browser) side without resorting to going back and forth between the server.

General usage of REST services

REST services are generally called when there is a transaction that needs to be performed or if it needs to retrieve data.

REST services are meant to be called by the client-side application and not the end user directly.

Authenticating

For any request to the server, part of the request should contain the authorization token. How it is implemented is application specific, but in general is either a BASIC or CERTIFICATE form of authentication.

Form based authentication is not used by REST services. However, as noted above REST services are not meant to be called by the user, but by the application. The application needs to manage getting the authentication token. In my case I used cookies with JASPIC with OAuth 2.0 to connect to Google for authentication and simple HTTP Authentication for automated testing. I also used HTTP Header authentication via JASPIC for local testing as well (though the same approach can be performed in SiteMinder)

As per those examples, the authentication is managed on the client side (though SiteMinder or Google would store the authentication session on their end), there's nothing that can be done about that state, but it is not part of the REST service application.

Retrieval requests

Retrieval requests in REST are GET operations where a specific resource is requested and is cacheable. There is no need for server sessions because the request has everything it would need to retrieve the data: authentication and the URI.

Transaction scripts

As noted above, the client-side application itself calls the REST services along with the authentication that it manages on the client side as well.

What this means for REST services [if done correctly] is to take a single request to the REST server will contain everything that is needed for a single user operation that does everything that is needed in a single transaction, a Transaction Script is what the pattern is called.

This is done through a POST request usually, but others such as PUT can also be used.

A lot of contrived examples of REST (I myself did this) tried to follow as much of what has been defined in the HTTP protocol, after going through that I decided to be more pragmatic and left it to GET and POST only. The POST method does not even have to implement the POST-REDIRECT-GET pattern.

Regardless though, as I had noted above, the client-side application will be the one calling the service and it will only call the POST request with all the data when it needs to (not every time). This prevents constant requests to the server.

Polling

Though REST can be used for polling as well, I won't recommend it unless you have to use it because of browser compatibility. For that I would use WebSockets which I had designed an API contract for as well. Another alternative for older browsers is CometD.

脱离于你 2024-09-14 07:04:16

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

以所有主要社交媒体应用程序为例——Tumblr、Instagram、Facebook 和 Twitter。它们都有一个永远滚动的视图,你向下滚动得越远,你看到的内容就越多,时间也越来越远。然而,我们都经历过这样的时刻:您丢失了滚动到的位置,并且应用程序将您重置回顶部。就像如果您退出应用程序,那么当您重新打开它时,您会再次回到顶部。

原因是服务器没有存储你的会话状态。遗憾的是,您的滚动位置仅存储在客户端的 RAM 中。

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

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


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

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

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

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

由于多种原因,它无法使用 MAC 地址,其中最重要的一点是,您可以在不同的浏览器和应用程序上同时登录多个不同的 Facebook 帐户。一种浏览器可以轻松冒充另一种浏览器,MAC 地址也同样容易被欺骗。

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


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


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

REST is very abstract. It helps to have some good, simple, real-world examples.

Take for example all major social media apps -- Tumblr, Instagram, Facebook, and Twitter. They all have a forever-scrolling view where the farther you scroll down, the more content you see, further and further back in time. However, we've all experienced that moment where you lose where you were scrolled to, and the app resets you back to the top. Like if you quit the app, then when you reopen it, you're back at the top again.

The reason why, is because the server did not store your session state. Sadly, your scroll position was just stored in RAM on the client.

Fortunately you don't have to log back in when you reconnect, but that's only because your client-side also stored login certificate has not expired. Delete and reinstall the app, and you're going to have to log back in, because the server did not associate your IP address with your session.

You don't have a login session on the server, because they abide by REST.


Now the above examples don't involve a web browser at all, but on the back end, the apps are communicating via HTTPS with their host servers. My point is that REST does not have to involve cookies and browsers etc. There are various means of storing client-side session state.

But lets talk about web browsers for a second, because that brings up another major advantage of REST that nobody here is talking about.

If the server tried to store session state, how is it supposed to identify each individual client?

It could not use their IP address, because many people could be using that same address on a shared router. So how, then?

It can't use MAC address for many reasons, not the least of which because you can be logged into multiple different Facebook accounts simultaneously on different browsers plus the app. One browser can easily pretend to be another one, and MAC addresses are just as easy to spoof.

If the server has to store some client-side state to identify you, it has to store it in RAM longer than just the time it takes to process your requests, or else it has to cache that data. Servers have limited amounts of RAM and cache, not to mention processor speed. Server-side state adds to all three, exponentially. Plus if the server is going to store any state about your sessions then it has to store it separately for each browser and app you're currently logged in with, and also for each different device you use.


So... I hope that you see now why REST is so important for scalability.
I hope you can start to see why server-side session state is to server scalability what welded-on anvils are to car acceleration.


Where people get confused is by thinking that "state" refers to, like, information stored in a database. No, it refers to any information that needs to be in the RAM of the server when you're using it.

酷炫老祖宗 2024-09-14 07:04:16

没有勺子。

不要将无状态性视为“一次又一次将您的所有内容发送到服务器”。决不。总会有状态 - 毕竟数据库本身就是一种状态,您是注册用户,因此如果没有服务器端,任何客户端信息集都将无效。从技术上讲,你永远不会真正无状态。

登录争论
    What does it even mean to not keep a session - and log in every time?

    有些意思是“每次都发送密码”,这简直是愚蠢的。有人说“当然不是,发送一个令牌” - 你瞧,PHP 会话就是这样做的。它发送一个会话 ID,这是一种令牌,它可以帮助您访问您的个人内容,而无需每次都重新发送 u/pw。它也非常可靠并且经过充分测试。是的,方便,但这可能会变成一个缺点,请参阅下一段。

减少占用空间
    What you should do, instead, and what makes real sense, is thin your webserver footprint to the minimum. Languages like PHP make it very easy to just stuff everything in the session storage - but sessions have a price tag. If you have several webservers, they need to share session info, because they share the load too - any of them may have to serve the next request.

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

所以你是说,将会话存储保持在最低限度?
    Again, it's your decision. You can store stuff there for performance reasons (database is almost always slower than Redis), you can store information redundantly, implement your own caching, whatever - just keep in mind that web servers will have a bigger load if you store a lot of rubbish on them. Also, if they break under heavy loads (and they will), you lose valuable information; with the REST way of thinking, all that happens in this case is the client sends the same (!) request again and it gets served this time.
那该怎么办呢?
    No one-fits-all solution here. I'd say choose a level of statelessness and go with that. Sessions may be loved by some and hated by others but they're not going anywhere. With every request, send as much information as makes sense, a bit more perhaps; but don't interpret statelessness as not having a session, nor as logging in every time. Somehow the server must know it's you; PHP session ids are one good way, manually generated tokens are another.

    Think and decide - don't let design trends think for you.

There is no spoon.

Don't think of statelessness like "sending all your stuff to the server again and again". No way. There will be state, always - database itself is a kind of state after all, you're a registered user, so any set of client-side info won't be valid without the server side. Technically, you're never truly stateless.

The Login Debate
    What does it even mean to not keep a session - and log in every time?

    Some mean "send the password each time", that's just plain stupid. Some say "nah of course not, send a token instead" - lo and behold, PHP session is doing just that. It sends a session id which is a kind of token and it helps you reach your personal stuff without resending u/pw every time. It's also quite reliable and well tested. And yes, convenient, which can turn into a drawback, see next paragraph.

Reduce footprint
    What you should do, instead, and what makes real sense, is thin your webserver footprint to the minimum. Languages like PHP make it very easy to just stuff everything in the session storage - but sessions have a price tag. If you have several webservers, they need to share session info, because they share the load too - any of them may have to serve the next request.

    A shared storage is a must. Server needs to know at least if someone's logged in or not. (And if you bother the database every time you need to decide this, you're practically doomed.) Shared storages need to be a lot faster than the database. This brings the temptation: okay, I have a very fast storage, why not do everything there? - and that's where things go nasty in the other way.

So you're saying, keep session storage to the minimum?
    Again, it's your decision. You can store stuff there for performance reasons (database is almost always slower than Redis), you can store information redundantly, implement your own caching, whatever - just keep in mind that web servers will have a bigger load if you store a lot of rubbish on them. Also, if they break under heavy loads (and they will), you lose valuable information; with the REST way of thinking, all that happens in this case is the client sends the same (!) request again and it gets served this time.
How to do it right then?
    No one-fits-all solution here. I'd say choose a level of statelessness and go with that. Sessions may be loved by some and hated by others but they're not going anywhere. With every request, send as much information as makes sense, a bit more perhaps; but don't interpret statelessness as not having a session, nor as logging in every time. Somehow the server must know it's you; PHP session ids are one good way, manually generated tokens are another.

    Think and decide - don't let design trends think for you.

萧瑟寒风 2024-09-14 07:04:16

我发现这里的基本问题是将 SessionState 混淆了。虽然 REST 指定您不应在服务器上存储状态,但没有什么可以阻止您存储会话

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

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

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

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

Santanu Dey 在他的回答中提供的视频链接很有帮助。如果还没有的话请注意。

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

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

I see that the basic issue here is mixing up Session with State. And while REST specifies that you should NOT store the State on the server, nothing prevents you from storing a user Session.

Managing the State on the server means that your server knows exactly what the client is doing (what page they're viewing in which section of the application). And this is what you shouldn't need to do.

I agree with the other people saying that you should keep the session storage to a minimum size; and while that's common sense, it's actually also dependent on the application.
So, in short, you can still keep a session with cached data to handle the requests with less load on the server, and manage the authentication by providing a temporary authentication/access token for the client to use. Whenever the session/token is expired, generate a new one and ask the client to use it.

Someone might argue that the client should better generate the token. I say it works both ways, and it would depend on the application, and who's going to work with the API.

Also keeping some sensitive session data on the server should be the right way to do. You cannot trust the client to keep their shopping cart that (for example) contains a field named "isFreeGift". Such information should be kept on the server.

The video link provided by Santanu Dey in his answer is helpful. Watch it if you haven't.

Just a side note: It seems all the answers already given seem to disregard the fact that some operations could cause a heavy load on the server. That's relevant in terms of power consumption, hardware consumption, and cost (for servers rented by CPU cycle). A good developer shouldn't be lazy in optimizing their application, even if the operation can be done very quickly on a modern CPU on some rented server for which they don't pay its electricity and maintenance bill.

Althoght the question is a few years old, I hope that my answer would still be helpful.

暗藏城府 2024-09-14 07:04:16

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

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

是的,http 协议本质上是一种无状态协议,但为了使其有状态,我们使用了 HTTP cookie。所以,默认情况下是 SOAP。但它同样可以是有状态的,具体取决于您使用的框架。

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

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

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

Stateless means the state of the service doesn’t persist between subsequent requests and response. Each request carries its own user credentials and is individually authenticated. But in stateful each request is known from any prior request. All stateful requests are session-oriented i.e. each request need to know and retain changes made in previous requests.

Banking application is an example of stateful application. Where user first login then make transaction and logs out. If after logout user will try to make the transaction, he will not be able to do so.

Yes, http protocol is essentially a stateless protocol but to make it stateful we make us of HTTP cookies. So, is SOAP by default. But it can be make stateful likewise, depends upon framework you are using.

HTTP is stateless but still we can maintain session in our java application by using different session tracking mechanism.

Yes, We can also maintain session in webservice whether it is REST or SOAP. It can be implemented by using any third party library or you can implement by our own.

Taken from http://gopaldas.org/webservices/soap/webservice-is-stateful-or-stateless-rest-soap

身边 2024-09-14 07:04:16

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

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

The major difference between stateless vs Stateful is the data being passed back to the server every time. In case of stateless, the client has to provide all the info so lot of parameters may need to be passed in each request. In Stateful, the cliet passes those parameters once and they are maintained by the server until modified by the client again.

IMO, API should be stateless which gives allows to scale up really quickly.

假面具 2024-09-14 07:04:16

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

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

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

会话 ID 可以通过对标识用户的内容进行单向锁定(加密)并将时间添加到会话 ID 中来生成,这样就可以定义会话的到期时间。

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

When you develop a RESTful service, in order to be logged in you will need your user to be authenticated. A possible option would be to send the username and password each time you intend to do a user action. In this case the server will not store session-data at all.

Another option is to generate a session-id on the server and send it to the client, so the client will be able to send session-id to the server and authenticate with that. This is much much safer than sending username and password each time, since if somebody gets their hand on that data, then he/she can impersonate the user until the username and password is changed. You may say that even the session id can be stolen and the user will be impersonated in that case and you are right. However, in this case impersonating the user will only be possible while the session id is valid.

If the RESTful API expects username and password in order to change username and password, then even if somebody impersonated the user using the session id, the hacker will not be able to lock out the real user.

A session-id could be generated by one-way-locking (encryption) of something which identifies the user and adding the time to the session id, this way the session's expiry time could be defined.

The server may or may not store session ids. Of course, if the server stores the session id, then it would violate the criteria defined in the question. However, it is only important to make sure that the session id can be validated for the given user, which does not necessitate storing the session id. Imagine a way that you have a one-way-encryption of email, user id and some user-specific private data, like favorite color, this would be the first level and somehow adding the username date to the encrypted string and apply a two-way encryption. As a result when a session id is received, the second level could be decrypted to be able to determine which username the user claims to be and whether the session time is right. If this is valid, then the first level of encryption could be validated by doing that encryption again and checking whether it matches the string. You do not need to store session data in order to achieve that.

生生漫 2024-09-14 07:04:16

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

这个 REST 无状态约束非常重要。如果不应用此约束,您的服务器端应用程序将无法扩展,因为要维护每个客户端会话将是它的致命弱点

You have to manage client session on the client side. This means that you have to send authentication data with every request, and you probably, but not necessary have an in-memory cache on the server, which pairs auth data to user information like identity, permissions, etc...

This REST statelessness constraint is very important. Without applying this constraint, your server side application won't scale well, because maintaining every single client session will be its Achilles' heel.

橙味迷妹 2024-09-14 07:04:16

REST 是无状态的,不会维护请求之间的任何状态。设置客户端 cookie/标头以维护用户状态(例如身份验证)。假设客户端用户名/密码由第三方身份验证机制(第二级 OTP 生成等)进行验证。一旦用户获得身份验证,标头/cookie 就会暴露出来,我们可以假设用户为身份验证,因为用户带有有效的标头/cookie 。现在,用户的某些信息(例如 IP)要么保存在缓存中,之后如果请求来自相同的 Ip(MAC 地址),则允许列出的资源用户。并且缓存会维护一段特定的时间,一旦时间过去,缓存就会失效。因此,可以使用缓存或使用数据库条目来保存请求中的信息。

REST is stateless and doesn’t maintain any states between the requests. Client cookies / headers are set to maintain the user state like authentication. Say Client username/password are validated by third part authentication mechanism – 2nd level OTP gerneation etc. Once user get authenticated – headers /cookies comes to rest service end point exposed and we can assume user as auth since user is coming with valid headers/cookies. Now certain info of user like IP is either maintained in the cache and after that if request is coming from same Ip (mac address) for listed resources User is allowed. And cache is maintained for some particular time which get invalidated once time lapses. So either cache can be used or DB entries can be used to persist info b/w the requests.

调妓 2024-09-14 07:04:16

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

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

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

希望这有帮助!

Stateless here means that state or meta data of request is not maintained on server side. By maintaining each request or user's state on server, it would lead to performance bottlenecks. Server is just requested with required attributes to perform any specific operations.

Coming to managing sessions, or giving customize experience to users, it requires to maintain some meta data or state of user likely user's preferences, past request history. This can be done by maintaining cookies, hidden attributes or into session object.

This can maintain or keep track of user's state in the application.

Hope this helps!

临走之时 2024-09-14 07:04:16

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

我强烈建议禁用 RESTFul 服务的 cookie 身份验证...查看基本/摘要身份验证 - 这对于基于 RESTFul 的服务来说应该足够了。

The whole concept is different... You don't need to manage sessions if you are trying to implement RESTFul protocol. In that case it is better to do authentication procedure on every request (whereas there is an extra cost to it in terms of performance - hashing password would be a good example. not a big deal...). If you use sessions - how can you distribute load across multiple servers? I bet RESTFul protocol is meant to eliminate sessions whatsoever - you don't really need them... That's why it is called "stateless". Sessions are only required when you cannot store anything other than Cookie on a client side after a reqest has been made (take old, non Javascript/HTML5-supporting browser as an example). In case of "full-featured" RESTFul client it is usually safe to store base64(login:password) on a client side (in memory) until the applictation is still loaded - the application is used to access to the only host and the cookie cannot be compromised by the third party scripts...

I would stronly recommend to disable cookie authentication for RESTFul sevices... check out Basic/Digest Auth - that should be enough for RESTFul based services.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文