我有一个具体的示例,可以忠实于RESTful原则,
无状态::一个客户端可以向服务器发送多个请求;但是,每个请求都必须独立,也就是说,每个请求都必须 包含所有必要的信息,以便服务器可以 了解并进行相应处理。在这种情况下,服务器 不得保留有关客户端状态的任何信息。任何信息 状态必须保留在客户端上,例如会话。 (引用自: 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来创建插入/记录。
现在我的问题是,这是否违反了宁静的api的无状态约束?
我可以双向争论:
否这不是违规,因为所有数据都是由客户端技术上提供的。尽管客户端要依靠某些应用程序逻辑来实现它。
是,这是违规的,因为客户端依赖于应用程序逻辑来获取用户ID。该应用程序必须查找用户ID,而不是客户端将其发送出去。
我之所以这样问,是因为我可以将id用作客户端需要提供的信息的一部分,但是由于需要accessToken,因此应用程序可以使用该ID来获取ID ...
也许我想得太多了?什么是最佳做法?这种情况取决于开发商吗?还有其他人遇到这个问题吗?您将如何处理?为什么?
侧面说明:我正在使用LoopBack进行构建。
修改:
所以我想这里有一个基本问题。可以使用访问令牌作为获取其他信息的手段吗?
答案 0 :(得分:1)
您没有想太多。实际上,在编写代码时牢记这些内容真是太好了。可能要花几年的时间,实际上要感谢您在查看代码时做出的明智决定。
现在进入主题。如果我是您,那么我将没有“ commonUserId”,而是出于安全考虑。因为我必须以任何一种方式验证commonUserId值,以查看它是否首先存在于我的系统中(不信任客户端输入)或它实际上属于身份验证用户(在您的情况下为访问令牌)。因此,出于这个原因,我会放弃它,而是依靠访问令牌和应用逻辑来识别用户。
确实可以使用任何一种情况,但是即使应用程序首先设置了该值,也要确保您不会盲目地信任客户端输入。
祝你好运!
答案 1 :(得分:1)
现在我的问题是,这是否违反了宁静的api的无状态约束?
无状态(在REST的上下文中)的明确定义来自Roy Fielding论文的第三章,其中他描述了Client-Stateless-Server分层样式
客户端无状态服务器样式从客户端服务器派生而来,其附加约束是服务器组件上不允许会话状态。从客户端到服务器的每个请求都必须包含理解该请求所需的所有信息,并且不能利用服务器上存储的任何上下文。
...可伸缩性得到了改善,因为不必在请求之间存储状态,这使得服务器组件可以快速释放资源并进一步简化实现。
Fielding论文的第6章讨论session cookies,描述了在服务器上存储会话状态的部分问题。
随后使用浏览器的历史记录功能(“后退”按钮)备份到cookie所反映的视图之前的视图时,浏览器的应用程序状态将不再与cookie中表示的存储状态匹配。因此,发送到同一台服务器的下一个请求将包含一个cookie,该cookie会歪曲当前应用程序上下文,从而导致双方混乱。
因此,您可以使用消息正文中的信息,并使用“应用程序逻辑”对其进行转换。同样,您可以在消息标题中使用信息,并使用“应用程序逻辑”进行转换。
您遇到麻烦的地方是使用请求中的信息来查找会话状态-也就是客户端在较早的消息中告诉您的内容。
可以依靠访问令牌作为获取其他信息的方式吗?
要看吗?
“此请求包含访问令牌12345,因此commonUserId应该为67890,因为令牌12345始终如此。”没关系。
“此请求包含访问令牌12345,因此commonUserId应该为67890,因为存在一个较早的请求,令牌12345告诉我们使用commonUserId 67890”。<-不是无状态的。
Kristopher Sandoval在stateful vs stateless web services上有一篇不错的文章,可能有助于澄清您的情况。
答案 2 :(得分:1)
我认为您在这里混合了两件事-请求身份验证和请求数据。
访问令牌可确保在令牌有效时应处理请求数据。
然后,您的应用程序的业务逻辑负责解释请求数据,将其映射到数据模型上,并确定在创建事件时用作用户ID的内容。想象一下,访问令牌只是将用户Admin标识为请求的发起者,而请求数据包含的用户Boy的ID为commonUserId
,该请求是由该用户为其创建事件的。
在loopbackjs
框架中,通常使用访问令牌来识别用户。