服务器端会话是否违反REST?


14

根据Roy Fielding(HTTP规范的主要作者之一)在讨论REST时的开创性论文《建筑风格》中提到,他提到:

从客户端到服务器的每个请求都必须包含理解该请求所需的所有信息,并且不能利用服务器上存储的任何上下文。

通过“存储的上下文”他指的是应用程序的状态如什么下一页的页码是对资源的状态,例如任何数据存储,图像等-这可以说是整点休息。

可以公平地说,大多数休息尝试(据此定义为符合上述论点的实现)都必须失败,因为它们依赖于在服务器上存储会话数据(持久性还是其他方式)?

会话的概念很常见-特别是对于Web开发人员-但是根据上面的定义它是否是RESTful的?


2
我会说,根据该定义,几乎没有什么是令人不安的,但是该定义又怎么合理呢?想象一下“宁静”的google搜索,您必须在向Google的请求中提供互联网索引,以便互联网为您搜索。什么?不,说您不能拥有一个持久性存储区并保持宁静就等于说宁静的接口实际上毫无意义。这并不意味着我们都应该开始维护内存会话并说它仍然是好的休息设计……
Jimmy Hoffa 2012年

3
我认为应该指出,应用程序状态资源状态之间是有区别的(Google索引将是资源状态,并且是完全合法的)。我应该在问题中更清楚地说明这一点。
马特

有这样的区别吗?请定义一下。:)我已经看到人们尝试过定义它们,但是由于它们实际上没有什么不同,所以它变得非常模糊。它们都是可变数据,一种状态与另一种状态之间唯一相关的区别是状态是否持久,其中非状态意味着通常可以再生,这就是使其与众不同的原因。
吉米·霍法

1
我自己想知道。既然没有人解释过为什么我的应用程序需要一个“宁静”的金色恒星,我也不用担心。
psr 2012年

Answers:


10

我会说是的,会话状态的确使RESTful应用成为非RESTful。举个小例子,我姐姐订阅了《华尔街日报》。她会定期阅读付费专页后面的内容,并决定将链接(通过她自己的电子邮件客户端,而不是通过WSJ)发送给没有WSJ帐户的朋友。单击,发送失败。显然,我姐姐在那个URL上的经历不同于她朋友的经历。

相关但不严格的主题:我正处于一个应用程序的早期设计阶段,该应用程序旨在支持网络上的大量研究工作(称为quests(请思考:类固醇和LSD上的书签))。任务的所有者希望与其他人共享其数据的特定视图,但是此视图需要UI状态(例如,哪些数据显示在哪些窗格中的哪些可视化效果)以及访问UI的适当权限的组合并显示数据。接收者需要很多存储状态才能获得预期的视图。

我目前的解决方案是将所有视图的UI / ACL /一切必要的信息存储在一个单独的对象和返回URL(可能是UUID)对象。我认为从某种意义上来说,访问视图对象可以被认为是RESTful的,因为拥有它的每个人都会获得相同的信息/体验。


1
您正在查看的对象示例在这方面是另一个角度。整齐。
马特

接受这个答案,尽管还有其他很好的答案,主要是因为它直接回答了问题并给出了一个非常清晰的例子。同样,视图对象上的第二部分倾斜了刻度。
马特

1
如果您说wsj网站是一个非静态应用程序的示例,那么我不同意您的示例显示了这一点。例如,如果WSJ站点完全依靠姐姐的客户提供的数据来呈现数据,那么@Matt给出的定义就是RESTful。但是,如果它依赖于临时的内存中会话状态,则根据定义,Matt给出的不是RESTful。我仅指出这一点,因为Matt给出的定义是基于实现细节的,而REST是通过消耗技术更好地定义的。
吉米·霍法

@JimmyHoffa-我对REST约束的理解是它是无状态的。对我来说,这似乎很明确。
彼得·罗威尔

如果WSJ应用程序没有状态,则必须由客户端发送可见文章。该文章可由站点管理员随时编辑,这毫无疑问是WSJ应用程序状态的一部分。我认为正在争取的区别是它是持久状态,因此与非持久状态(例如会话)相比,它具有更多的保证和更少的管理开销,并且在它的事务中具有更简单的原子性控制。人们希望这些与简单的消费模型一起休息。(我认为)
吉米·霍法

2

服务器端会话是否违反REST?

他们一定会!实施REST时,必须没有服务器端会话,否则,您将具有混合RPC / REST解决方案。

每次发出新请求时,客户端必须向RESTful服务发送服务该请求所需的所有上下文,包括认证客户端所需的信息。服务器可以自由地缓存信息以更快地处理后续请求,但是缓存的信息不得等于服务器端会话。换句话说,即使没有缓存状态,请求本身也必须包含足以处理的信息。


1

可能取决于您所说的“会话数据”。这是一个精确的词吗?

双方之间的安全通信通常涉及服务器生成(和存储)限时的“访问令牌”,客户端必须随授权向每个请求提供该令牌。这个访问令牌已经是我所谓的“会话数据”了-它存储在服务器端,有时间限制,并且与一个客户端(通常是他的权限)相关。

如果将这种操作标记为非RESTful,我会感到非常惊讶。OAuth是一个示例。

我不是专家,在这里我也不是很自信。我只是分享我的见解,希望它们能对您有所帮助。


1

REST最重要的一点是,资源的URI始终指向相同的资源。因此,用户可以传递对此资源的引用,并且每个人都可以看到相同的内容。这称为代表性状态转移(REST)。如果服务器保持状态并为相同的URI提供不同的资源,我会说这不再是纯REST。


用户看到相同的东西并不一定是正确的。访问权限可以决定任何一个用户看到的内容。
Erik 2014年

@Erik但是用户会声明他们希望在请求中看到多少(包括使用Accept Header),因此Puckl的答案成立。
约翰,2014年

1
@Johan我将从同一个端点为不同的用户返回不同的数据。否则,对用户进行身份验证有什么意义?
Erik

@Erik我也会这样做。尽管如此,我仍然相信身份验证不在资源状态之内,因此严格来说,如果视图受身份验证的用户影响,则它不再是RESTful的。也许,如果您想使用RESTful徽章,则应创建资源的多个“视图”,具体取决于谁请求访问,该资源仅授权访问某些视图。因此,公众可以访问/ userprofiles / {userID} / publicview,而用户可以访问/ userprofiles / {userID} / fullprofile,授权的朋友可以访问/ userprofiles / {userID} / friendsview
约翰

0

会话基本上用于向无状态的RESTful应用程序添加状态。因此,从形式上讲,这使您的RESTful应用程序成为有状态的,但是让服务器保持状态会使您的生活变得更轻松,因为您不必在每个请求/响应上来回传递所有数据。

会话(更一般地说,状态)使您可以避免这种情况,这在性能(传输的数据较少)和安全性(可用于篡改的数据较少)方面具有一些积极的好处。

因此,尽管它正式违反了REST定义的一部分,但它是如此有用,以至于很少见到通过会话使用状态的RESTful应用程序。


我不同意。您有一个购物网站,可让您按品牌,颜色和大小进行过滤。传统的Web 1.0网站会通过一些复选框,服务器端会话和POST处理此问题。如果我要共享指向example.org/shirts的链接,人们不会看到我选择了Medium,Black和Roots。(当您单击返回时,这还会导致难看的“您正在重新发布数据”消息。)但是,如果我共享指向(例如)example.org/shirts/medium-black-roots的链接,则每个人都有相同的表示形式。所有必要的状态信息都位于URL中(如果需要,则为POST正文,但您不能共享)。
杰西·布坎南

... RESTful可能并不适合所有情况。您的假设应用程序是否面向资源(购物网站一定是!)?也许它不适合具有很多状态且不面向资源的RIA。老实说,我想不出任何好的例子。
杰西·布坎南

0

该声明的意思是Fielding托管REST API的应用程序服务器不会通过某种幕后机制将环境状态与请求关联。考虑一下应用程序服务器数据库服务器之间的区别。REST约束是应用程序服务器应该是无状态的。但是,应用程序服务器可以基于作为请求一部分的信息(例如,授权标头中的用户/密码组合或Uri本身)将对资源状态的请求委托给数据库服务器。毕竟,REST是基于客户端/服务器模型的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.