在RESTful API中使用会话真的违反了RESTful吗?我已经看到了许多意见,但我不相信会议是不安宁的。在我看来:

rest不禁止身份验证(否则在RESTful服务中几乎没有用处) 身份验证是通过在请求中发送一个身份验证令牌来完成的,通常是头 这个身份验证令牌需要以某种方式获得,并且可能会被撤销,在这种情况下需要更新 身份验证令牌需要由服务器验证(否则就不是身份验证)

那么会话是如何违背这一点的呢?

客户端,会话是使用cookie实现的 cookie只是一个额外的HTTP报头 会话cookie可以在任何时候获得和撤销 如果需要,会话cookie可以有无限的生存时间 会话id(身份验证令牌)在服务器端得到验证

As such, to the client, a session cookie is exactly the same as any other HTTP header based authentication mechanism, except that it uses the Cookie header instead of the Authorization or some other proprietary header. If there was no session attached to the cookie value server-side, why would that make a difference? The server side implementation does not need to concern the client as long as the server behaves RESTful. As such, cookies by themselves should not make an API RESTless, and sessions are simply cookies to the client.

我的假设错了吗?是什么使会话cookie不安分?


首先,REST不是宗教,不应该被当作宗教来对待。虽然REST式服务有很多优点,但您应该只在应用程序有意义时才遵循REST的原则。

That said, authentication and client side state do not violate REST principles. While REST requires that state transitions be stateless, this is referring to the server itself. At the heart, all of REST is about documents. The idea behind statelessness is that the SERVER is stateless, not the clients. Any client issuing an identical request (same headers, cookies, URI, etc) should be taken to the same place in the application. If the website stored the current location of the user and managed navigation by updating this server side navigation variable, then REST would be violated. Another client with identical request information would be taken to a different location depending on the server-side state.

Google's web services are a fantastic example of a RESTful system. They require an authentication header with the user's authentication key to be passed upon every request. This does violate REST principles slightly, because the server is tracking the state of the authentication key. The state of this key must be maintained and it has some sort of expiration date/time after which it no longer grants access. However, as I mentioned at the top of my post, sacrifices must be made to allow an application to actually work. That said, authentication tokens must be stored in a way that allows all possible clients to continue granting access during their valid times. If one server is managing the state of the authentication key to the point that another load balanced server cannot take over fulfilling requests based on that key, you have started to really violate the principles of REST. Google's services ensure that, at any time, you can take an authentication token you were using on your phone against load balance server A and hit load balance server B from your desktop and still have access to the system and be directed to the same resources if the requests were identical.

归根结底,您需要确保您的身份验证令牌是针对某种类型的备份存储(数据库、缓存等)进行验证的,以确保您尽可能多地保留REST属性。

我希望你能理解。如果你还没有,你也应该看看维基百科文章中关于具象状态转移的约束部分。关于REST的原则实际上在争论什么以及为什么争论,它特别具有启发性。

会话不是不安分的 你是说REST服务只用于http还是我弄错了?基于cookie的会话只能用于自己的(!)基于http的服务!(这可能是一个问题与cookie工作,例如从移动/控制台/桌面/等) 如果你为3d开发者提供RESTful服务,永远不要使用基于cookie的会话,而是使用令牌来避免安全问题。

Cookies are not for authentication. Why reinvent a wheel? HTTP has well-designed authentication mechanisms. If we use cookies, we fall into using HTTP as a transport protocol only, thus we need to create our own signaling system, for example, to tell users that they supplied wrong authentication (using HTTP 401 would be incorrect as we probably wouldn't supply Www-Authenticate to a client, as HTTP specs require :) ). It should also be noted that Set-Cookie is only a recommendation for client. Its contents may be or may not be saved (for example, if cookies are disabled), while Authorization header is sent automatically on every request.

另一点是,要获得授权cookie,您可能需要首先在某个地方提供您的凭据。如果是这样,那不就是不安分吗?简单的例子:

您尝试没有cookie的GET /a 你得到了一个授权请求 然后授权POST /auth 你会得到Set-Cookie 您尝试GET /a与cookie。但是在这种情况下GET /a的行为是幂等的吗?

总而言之,我认为如果我们访问某些资源并且需要进行身份验证,那么我们必须在同一资源上进行身份验证,而不是在其他任何地方。

首先,让我们定义一些术语:

RESTful: One can characterise applications conforming to the REST constraints described in this section as "RESTful".[15] If a service violates any of the required constraints, it cannot be considered RESTful. according to wikipedia. stateless constraint: We next add a constraint to the client-server interaction: communication must be stateless in nature, as in the client-stateless-server (CSS) style of Section 3.4.3 (Figure 5-3), such that each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server. Session state is therefore kept entirely on the client. according to the Fielding dissertation.

所以服务器端会话违反了REST的无状态约束,RESTfulness也一样。

因此,对于客户端来说,会话cookie与其他cookie完全相同 其他基于HTTP头的身份验证机制,除了它使用 Cookie报头,而不是授权或其他 专有的头。

通过会话cookie,您可以将客户端状态存储在服务器上,因此您的请求具有上下文。让我们尝试向系统中添加一个负载均衡器和另一个服务实例。在这种情况下,您必须在服务实例之间共享会话。这样的系统很难维护和扩展,所以扩展性很差……

在我看来,饼干并没有什么错。cookie技术是一种客户端存储机制,存储的数据被每个请求自动附加到cookie头。我不知道REST约束在这种技术上有什么问题。所以技术本身没有问题,问题在于它的使用。Fielding写了一个关于为什么他认为HTTP cookie是不好的小节。

在我看来: rest不禁止身份验证(否则在RESTful服务中几乎没有用处) 身份验证是通过在请求中发送一个身份验证令牌来完成的,通常是头 这个身份验证令牌需要以某种方式获得,并且可能会被撤销,在这种情况下需要更新 身份验证令牌需要由服务器验证(否则就不是身份验证)

你的观点很可靠。唯一的问题是在服务器上创建身份验证令牌的概念。你不需要那部分。您所需要的是在客户端存储用户名和密码,并在每次请求时发送它。你只需要HTTP基本认证和加密连接就可以做到这一点:

图1。—可信客户端无状态认证

您可能需要在服务器端使用内存中的身份验证缓存来提高速度,因为您必须对每个请求进行身份验证。

Now this works pretty well by trusted clients written by you, but what about 3rd party clients? They cannot have the username and password and all the permissions of the users. So you have to store separately what permissions a 3rd party client can have by a specific user. So the client developers can register they 3rd party clients, and get an unique API key and the users can allow 3rd party clients to access some part of their permissions. Like reading the name and email address, or listing their friends, etc... After allowing a 3rd party client the server will generate an access token. These access token can be used by the 3rd party client to access the permissions granted by the user, like so:

图2。—第三方客户端无状态认证

So the 3rd party client can get the access token from a trusted client (or directly from the user). After that it can send a valid request with the API key and access token. This is the most basic 3rd party auth mechanism. You can read more about the implementation details in the documentation of every 3rd party auth system, e.g. OAuth. Of course this can be more complex and more secure, for example you can sign the details of every single request on server side and send the signature along with the request, and so on... The actual solution depends on your application's need.

实际上,正如通用资源标识符所指示的那样,RESTfulness只应用于资源。因此,在REST中谈论诸如头文件、cookie等都是不合适的。REST可以在任何协议上工作,即使它通常是在HTTP上完成的。

主要的决定因素是:如果您发送一个REST调用(它是一个URI),那么一旦调用成功地到达服务器,假定没有执行转换(PUT、POST、DELETE),该URI是否返回相同的内容?这个测试将排除错误或正在返回的身份验证请求,因为在这种情况下,请求还没有到达服务器,这意味着servlet或应用程序将返回与给定URI对应的文档。

同样,在POST或PUT的情况下,是否可以发送给定的URI/有效负载,并且无论发送多少次消息,它都将始终更新相同的数据,以便后续的get将返回一致的结果?

REST是关于应用程序数据的,而不是关于传输数据所需的低级信息。

在下面这篇博文中,Roy Fielding对整个REST思想做了一个很好的总结:

http://groups.yahoo.com/neo/groups/rest-discuss/conversations/topics/5841

"A RESTful system progresses from one steady-state to the next, and each such steady-state is both a potential start-state and a potential end-state. I.e., a RESTful system is an unknown number of components obeying a simple set of rules such that they are always either at REST or transitioning from one RESTful state to another RESTful state. Each state can be completely understood by the representation(s) it contains and the set of transitions that it provides, with the transitions limited to a uniform set of actions to be understandable. The system may be a complex state diagram, but each user agent is only able to see one state at a time (the current steady-state) and thus each state is simple and can be analyzed independently. A user, OTOH, is able to create their own transitions at any time (e.g., enter a URL, select a bookmark, open an editor, etc.)."


至于身份验证的问题,无论它是通过cookie还是报头完成的,只要信息不是URI和POST有效负载的一部分,它就与REST完全没有关系。因此,关于无状态,我们只讨论应用程序数据。

例如,当用户在GUI屏幕上输入数据时,客户端会跟踪哪些字段已经输入,哪些字段没有输入,哪些必需的字段丢失等等。这都是CLIENT CONTEXT,服务器不应该发送或跟踪。发送到服务器的是需要在IDENTIFIED资源中(通过URI)修改的完整字段集,以便在该资源中发生从一个RESTful状态到另一个RESTful状态的转换。

因此,客户端会跟踪用户正在做什么,并且只向服务器发送逻辑上完整的状态转换。

HTTP事务,基本访问身份验证,不适合RBAC,因为基本访问身份验证每次都使用加密的用户名:密码进行标识,而RBAC中需要的是用户希望用于特定调用的Role。 RBAC不验证用户名上的权限,但验证角色上的权限。

您可以像这样进行连接:usernameRole:password,但这是一种糟糕的做法,而且效率也很低,因为当一个用户拥有更多角色时,身份验证引擎将需要在连接中测试所有角色,并且每次调用都需要再次测试。这将破坏RBAC最大的技术优势之一,即非常快速的授权测试。

因此,使用基本的访问身份验证无法解决这个问题。

为了解决这个问题,会话维护是必要的,根据一些回答,这似乎与REST相矛盾。

这就是我喜欢REST不应被视为宗教的答案。在复杂的业务案例中,例如在医疗保健领域,RBAC是绝对常见和必要的。如果他们不被允许使用REST,那将是一个遗憾,因为所有的REST工具设计者都将REST视为一种宗教。

对我来说,在HTTP上维护会话的方法并不多。可以使用带有sessionId的cookie,也可以使用带有sessionId的报头。

如果有人有别的想法,我很乐意听听。

我认为令牌必须包括所有需要的信息编码在它里面,这使得身份验证通过验证令牌和解码信息 https://www.oauth.com/oauth2-servers/access-tokens/self-encoded-access-tokens/

不,使用会话并不一定违反restful。如果您坚持REST规则和约束,那么使用会话(维护状态)将是多余的。毕竟,RESTfulness要求服务器不维护状态。

据我所知,当我们谈论会话时,有两种类型的状态

客户端和服务器交互状态 资源状态

这里的无状态约束指的是Rest中的第二种类型。使用cookie(或本地存储)并不违反Rest,因为它与第一个相关。

菲尔丁说:“从客户端到服务器的每个请求都必须包含理解请求所需的所有信息,并且不能利用服务器上存储的任何上下文。因此会话状态完全保存在客户端上。

这里的问题是,服务器上要完成的每个请求都需要来自客户端的所有必要数据。那么这就被认为是无状态的。再说一遍,我们这里说的不是饼干,我们说的是资源。