当 URI 上没有用户 ID 时如何设计 RESTful API URI

How to design RESTful API URI when you can't have user ID on the URI

Make-up 场景:

假设我正在构建一个 RESTful Web API 后端来管理会员的付款计划:

现在,如果我想设计一个 API 端点来 return 有关会员有效付款计划的信息,我通常会这样做:

/members/{member-id}/plans/active

我知道这可能是 a bad idea to put state on the URI(我有一个单独的问题),但请耐心等待。

现在是棘手的部分:公司的政策规定我不能在 URI 中包含会员 ID。他们将在 HTTP header 中拥有某种令牌,这是访问包含成员 ID 的 RESTful API 端点所必需的。

我的 API 应用程序,顺便说一下,它是 ASP.NET Core Web API,创建过滤器来解析该令牌并将其转换为成员 ID 没有问题,在代码。只是我的 API URI 不能再有成员 ID。

在这种情况下,您将如何设计 URI?

没有 URI 上的会员 ID,我的看起来像

/plans/active

现在数据将全部由该会员 ID driven/filtered 安全地存储在 API 后端。这正常吗?

在我看来这很正常。例如,当您使用 JWT 令牌进行身份验证时,通常就是这种情况。令牌不仅对用户进行身份验证,还包含有关它的相关信息。

在这些情况下,您还会看到具有此类端点的 API,但路径中没有任何关于用户的明确信息(如 ID 或其他信息)。

只是我的建议或观点,我实际上会将 members 部分保留在路径中:/members/plans/active.

the data now would be all driven/filtered by that member ID, securely inside the API backend. Is this normal?

在我看来,事情似乎在横向发展;好像人们不理解 REST,或者人们不理解他们试图实现的目标并不适合 适合 REST。

In order to obtain a uniform interface, multiple architectural constraints are needed to guide the behavior of components. REST is defined by four interface constraints: identification of resources.... -- Fielding, 2000

REST uses a resource identifier to identify the particular resource involved in an interaction between components. REST connectors provide a generic interface for accessing and manipulating the value set of a resource, regardless of how the membership function is defined or the type of software that is handling the request. The naming authority that assigned the resource identifier, making it possible to reference the resource, is responsible for maintaining the semantic validity of the mapping over time (i.e., ensuring that the membership function does not change). -- Fielding, 2000

Web 以统一资源标识符 标识资源的共同理解为基础。 URI 是 key/value 商店的关键字。当您开始将识别信息移动到请求的其他部分时,您就选择退出了由其他人共享的“统一界面”。这会使互操作性面临风险。

另一方面,许多 Web 还假定标识符已发布,并且通常没有很多纪律来限制对它们的复制。因此,您当然不希望包含机密 and/or 敏感信息。

REST 中的答案是使用另一层间接。规则是我们应该使用 URI,每个标识符都应该映射到一个资源。但是没有规则说 URI 的拼写必须与资源的语义相匹配。

换句话说:URL 起酥油有效!

GET /99bfb1e3-89a4-4a44-a6d7-0e70c209f447 HTTP/1.1

就 REST 而言,这是一个完全有效的请求,具有完全令人满意的标识符。只要您的服务器知道如何使用该密钥查找机密,就可以了。

当然,您可以将语义信息添加到不敏感的 URI 中,以帮助人们适应上下文

GET /members/99bfb1e3-89a4-4a44-a6d7-0e70c209f447/plans/active HTTP/1.1
GET /members/plans/active/99bfb1e3-89a4-4a44-a6d7-0e70c209f447 HTTP/1.1
GET /members/plans/active?99bfb1e3-89a4-4a44-a6d7-0e70c209f447 HTTP/1.1

这些也都可以(同样,假设您可以使用提供的信息来发现您需要 produce/modify 相应资源的敏感信息)。


另一方面,如果您的组织的担忧与泄漏标识符本身有关...那么有资历的人应该真正挑战 REST/HTTP 是问题的正确答案的假设。

随着您进一步偏离 HTTP 消息的“标准”,您会增加某些通用组件无法理解正在发生的事情的风险,如果这会导致 属性, 你的律师不会高兴的。