api - 通过辅助(秘密)ID 检索资源的最佳(RESTful?)方法是什么?
问题描述
我正在开发一个用于帐户邀请的 API,其中一个用户为另一个用户创建了加入平台的邀请,并具有一些特定的权限集。邀请本身将采用众所周知的电子邮件形式,其中包含带有一些随机密钥的链接以接受邀请,类似于我们通常看到的密码重置和帐户确认流程正在实施。
与许多其他 API 一样,此 API 将具有常规的 CRUD 操作,例如 POST /invites/
、 GET /invites/{id}
、 DELETE/invites/{id}
等,基于邀请实体的实际 ID 并实施常规授权方案。但我们还需要一种通过辅助 ID(链接中使用的秘密标识符)检索邀请的方法。
可以考虑只使用秘密作为邀请的主要标识符,但这会产生问题。由于知道秘密意味着允许应用邀请,因此秘密本身不应(总是)被其他 CRUD 调用暴露;对 GET 的响应/invites/
通常不包含秘密,这使得在邀请上执行任何其他操作(例如 DELETE)变得有问题。
关于通过多个标识符引用资源的方法已经有几个很好的问题,例如REST API DESIGN - 通过 REST 获取具有不同参数但相同 url 模式和它指向的其他几个资源的资源。通常他们归结为:
- 建议解决方案,例如
/foos/{id}
通过主 ID/foos/field/{value}
引用和通过另一个字段引用,在这种情况下,这将是秘密。但是我觉得这使得 URI 结构模棱两可,因为/foos/field/{value}
也可以被解读为引用 ID 为“field”的 foo 的“{value}”字段。由于 ID 通常是随机生成的,因此 ID 和资源中的实际字段名称甚至可能会发生冲突。 - 声明应该有 1 个 URI 来引用 1 个资源,暗示 1 个主要标识符,并建议通过该主要标识符以外的任何内容引用资源应该表示为应该返回集合的过滤器查询。所以 URI 会变成
/invites/?secret={secret}
. 然而,这并不“感觉正确”,因为秘密实际上确实指的是一种资源。此外,这个“秘密”字段本身可能甚至不会在资源表示中公开,让人觉得可以“过滤”它有点奇怪。
人们还普遍指出,从来没有真正需要通过多个唯一标识符来引用实体。但是,如何实现这样的用例呢?
过去我通过使用过滤器模式解决了类似的情况,但由于我一直遇到这种情况,我真的很好奇是否有更好的解决方案。
解决方案
我最终想出的是定义一个新的集合'authLinks',是'authenticated links'的缩写。“秘密”是此集合中实体的主要标识符。这些实体有一个“资源”字段,它是此 authLink 公开的资源(在本例中为邀请)的链接。当从 API 检索到这样的“authLink”时,服务器将使用它自己的内部凭据检索链接的资源,并将其作为“计算”字段resolvedResource 包含在响应中。
那么,交互将是什么样子:
POST `/authLinks/supserSecretSecret` {"resource": "/invites/someId"} (with appropriate credentials)
> `{"id": "supserSecretSecret", "resource": "/invites/someId", "resolvedResource": {"id": "someId", ...}}`
GET `/authLinks/supserSecretSecret` (without credentials)
> `{"id": "supserSecretSecret", "type": "invite", "resource": "/invites/someId", "resolvedResource": {"id": "someId", ...}}`
系统组件和管理员可以为新的或现有的资源(例如邀请或任何其他类型)CRUD 此类 authLink,并使用适当的创建、更新、删除权限方案。阅读不需要任何权限。
在某些情况下,实现只读机制可能是合适的。尽管我们应该问自己,在这种情况下(否),网络 GET 是否是检索数据的合适方法,但绝对不要忘记设置适当的标头以防止缓存。
对于我的情况,这以一种通用的方式很好地解决了问题,即对于需要通过共享秘密链接访问的任何类型的资源。
推荐阅读
- javascript - 如何重新组织数据以显示字符串在数组对象中出现的次数?
- vue.js - 如何在 NativeScript-Vue 中将 JSON 数据从 URL 插入到 ListView
- javascript - 有没有办法使用 Mapbox 向通过 AJAX 回调生成的数据添加图层?
- javascript - 如何通过 Pug 或 JS 将活动类添加到导航链接
- sql - 创建客户订单月度报告
- powershell - 内容长度和 Invoke-WebRequest
- python - 没有托管服务器的python repo
- julia - 闭包列表的类型稳定性
- node.js - 使用书架的 withRelated() 检索深度嵌套的关系
- php - for循环中的递增数组键