【问题标题】:What is the best (RESTful?) way to retrieve a resource by a secondary (secret) ID?通过辅助(秘密)ID 检索资源的最佳(RESTful?)方法是什么?
【发布时间】:2021-02-02 03:34:35
【问题描述】:

我正在开发一个用于帐户邀请的 API,其中一个用户为另一个用户创建一个加入平台的邀请,并具有一些特定的权限集。邀请本身将采用众所周知的电子邮件形式,其中包含带有随机密钥的链接以接受邀请,类似于我们通常看到的密码重置和帐户确认流程正在实施。

与许多其他 API 一样,此 API 将具有常规的 CRUD 操作,例如 POST /invites/、GET /invites/{id}、DELETE /invites/{id} 等,基于邀请实体的实际 ID 并实施常规授权方案.但我们还需要一种通过辅助 ID(链接中使用的秘密标识符)检索邀请的方法。

可以考虑只使用密钥作为邀请的主要标识符,但这会产生问题。由于知道秘密意味着允许应用邀请,因此秘密本身不应(总是)被其他 CRUD 调用暴露;对 GET /invites/ 的响应通常不会包含机密信息,这使得对邀请执行任何其他操作(例如 DELETE)都存在问题。

关于通过多个标识符引用资源的方法已经有几个很好的问题,例如REST API DESIGN - Getting a resource through REST with different parameters but same url pattern 和它指向的其他几个。通常他们归结为:

  • 建议解决方案,例如 /foos/{id} 用于通过主 ID 引用,/foos/field/{value} 用于通过另一个字段进行引用,在这种情况下,这将是秘密。但是我觉得这使得 URI 结构模棱两可,因为/foos/field/{value} 也可以被解读为引用 ID 为“field”的 foo 的“{value}”字段。由于 ID 通常是随机生成的,因此 ID 甚至可能与资源中的实际字段名称发生冲突。
  • 声明应该有 1 个 URI 来引用 1 个资源,暗示 1 个主要标识符,并建议通过该主要标识符以外的任何内容引用资源应该表示为应该返回集合的过滤器查询。所以 URI 会变成/invites/?secret={secret}。然而,这并不“感觉正确”,因为秘密实际上确实指的是一种资源。此外,这个“秘密”字段本身可能甚至不会在资源表示中公开,让人觉得可以对其进行“过滤”有点奇怪。

通常还指出,从来没有真正需要通过多个唯一标识符来引用实体。但是,如何实现这样的用例呢?

过去我使用过滤器模式解决了类似的情况,但由于我不断遇到这种情况,我真的很好奇是否有更好的解决方案。

【问题讨论】:

    标签: api rest uri api-design


    【解决方案1】:

    我最终想出的是定义一个新集合'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", ...}}`
    

    系统组件和管理员可以为新的或现有的资源(例如邀请或任何其他类型)使用适当的创建、更新、删除权限方案对此类 authLink 进行 CRUD。阅读不需要任何权限。

    在某些情况下,实现只读机制可能是合适的。虽然我们应该问自己,在这种情况下(否),网络 GET 是否是检索数据的合适方法,但绝对不要忘记设置适当的标头以防止缓存。

    对于我的情况,这以一种通用的方式很好地解决了问题,即对于需要通过共享秘密链接访问的任何类型的资源。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多