RESTful 最佳实践。这是否违反了无状态约束?

RESTful best practice. Does this violate the Stateless constraint?

我有一个关于忠于 RESTful 原则的具体例子,特别是:

Stateless: One client can send multiple requests to the server; however, each of them must be independent, that is, every request must contain all the necessary information so that the server can understand it and process it accordingly. In this case, the server must not hold any information about the client state. Any information status must stay on client – such as sessions. (quoting from: https://www.dineshonjava.com/what-is-rest-and-rest-architecture-and-rest-constraints/)

现在假设用户可以通过发布以下内容来创建新事件:

{
  "name": "string",
  "radius": 50,
  "status": 0,
  "location": {
    "lat": 0,
    "lng": 0
  },
  "commonUserId": 0
}

应用程序的设置方式使用户可以通过发布以下内容来完成同样的事情:

{
  "name": "testing",
  "radius": 50,
  "status": 0,
  "location": {
    "lat": 0,
    "lng": 0
  }
}

请注意 commonUserId 在第二个示例中不存在。 commonUserId 是数据库中的外键,是创建新记录所必需的。

不需要创建新记录的原因是因为应用程序正在使用客户端提供的访问令牌通过某种逻辑获取用户 ID(经过身份验证的用户 ID)。然后应用程序使用检索到的 ID(从逻辑中)来创建 insert/record。

现在我的问题是这是否违反了 restful api 的无状态约束?

我可以从两个方面进行论证:

这不是违规,因为所有数据都是客户提供的技术。尽管客户端依赖于某些应用程序逻辑来实现它。

这是违规行为,因为客户端依赖于应用程序逻辑来获取用户 ID。应用程序必须查找与客户端发送它相对的用户 ID。

我问这个的原因是因为我可以将 id 作为客户端需要提供的信息的一部分,但是由于 accessToken 是必需的,应用程序可以使用它来获取 id...

也许我想太多了?什么是最佳实践?这种情况是由开发商决定的吗?还有其他人遇到这个问题吗?你会如何处理这个问题,为什么?

旁注:我正在使用 LoopBack 构建它。

编辑:

所以我想这里有一个潜在的问题。可以依赖访问令牌作为获取其他信息的手段吗?

你没有想太多。在编写代码时牢记这些事情实际上很棒。几年后的某些人在查看代码时实际上会感谢您做出正确的决定。

进入正题。如果我是你,我不会有 "commonUserId" 并且我是从安全角度这么说的。因为我必须以任何一种方式验证 commonUserId 值,以查看它是否首先存在于我的系统中(不要相信客户端输入)或者它实际上属于经过身份验证的用户(在您的情况下是访问令牌)。因此,出于这个原因,我会取消它并依靠访问令牌和应用程序逻辑来识别用户。

案例确实可以用任何一种方式制作,但请确保您不要盲目相信客户端输入,即使应用程序首先设置了该值。

祝你好运!

Now my question is does this violate the stateless constraint of a restful api?

无状态(在 REST 上下文中)的最终定义来自 Roy Fielding 论文的第三章,他在其中描述了 Client-Stateless-Server 层次结构样式

The client-stateless-server style derives from client-server with the additional constraint that no session state is allowed on the server component. 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.

... Scalability is improved because not having to store state between requests allows the server component to quickly free resources and further simplifies implementation.

Fielding 论文的第 6 章,他讨论了 session cookies,描述了在服务器上存储会话状态的部分问题。

When the browser's history functionality (the "Back" button) is subsequently used to back-up to a view prior to that reflected by the cookie, the browser's application state no longer matches the stored state represented within the cookie. Therefore, the next request sent to the same server will contain a cookie that misrepresents the current application context, leading to confusion on both sides.

所以你可以利用消息体中的信息,用“应用逻辑”来改造它。同样,您可以使用消息头中的信息,并使用“应用程序逻辑”对其进行转换。

您遇到麻烦的地方是使用请求中的信息来查找会话状态——也就是客户在之前的消息中告诉您的内容。

Is it ok to rely on the access token as a means to get other pieces of information?

这取决于?

“此请求包含访问令牌 12345,因此 commonUserId 应为 67890,因为令牌 12345 始终如此。”应该没问题。

“此请求包含访问令牌 12345,因此 commonUserId 应为 67890,因为之前有一个令牌 12345 的请求告诉我们使用 commonUserId 67890”<-- 不是无状态的。

Kristopher Sandoval 有一篇关于 stateful vs stateless web services 的好文章,可能有助于澄清您的案例。

我认为您在这里混淆了两件事 - 请求身份验证和请求数据。

访问令牌确保在令牌有效时处理请求数据。

然后您的应用程序的业务逻辑负责解释请求数据,将其映射到您的数据模型并决定在创建事件时使用什么作为用户 ID。想象一下,访问令牌只是将用户 Admin 标识为请求的发起者,并且请求数据包含用户 Boy 的 id 作为 commonUserId 请求为其创建事件。

使用访问令牌来识别用户是 loopbackjs 框架的常见做法。