14

设计一个 RESTful API。我有两种识别资源(个人数据)的方法。通过数据库生成的唯一 ID,或通过为每个人输入的社会安全号码 (SSN)。SSN 应该是唯一的,但可以更改。

使用 ID 对我来说最方便,因为它保证是唯一的,并且不会改变。因此,资源的 URL 也始终保持不变:

GET /persons/12

{
  "name": Morgan
  "ssn": "840212-3312"
}

使用 SSN 的理由是它更能被 API 客户端提供信息和理解。SSN在周边系统中也使用较多:

GET /persons/840212-3321

{
  "name": Morgan
  "id": "12"
}

所以问题是:我是否应该采用第一种方法,并避免 SSN 可能发生变化的一些实施难题。也许提供一些从 SSN 转换为 ID 的辅助方法?

或者采用第二种方法。提供更多信息的 API。尽管必须处理一些不那么 RESTful 的奇怪问题,其中 URL:s 可能由于 SSN 更改而更改?

4

4 回答 4

9

URL 设计是个人选择。但是为了给你一些与雷已经提供的不同的例子,我会给你一些我自己的。

我有一个用户帐户资源并允许通过两个 URI 进行访问:

/users/12

/users/morgan

其中数值是自动增量 ID,字母值是用户指定的系统上的唯一用户名。这些资源是无法访问的,所以我不关心规范化,但是/users页面链接到字母表。

我的系统上没有其他资源具有两个唯一字段,因此由 ID、/jobs/123、 . 引用/quotations/456

如您所见,我更喜欢复数 URI 段 ;-)
我认为“job 123”来自“jobs”集合,因此拥有一个“jobs”资源似乎是合乎逻辑的,每个作业都有子资源。

您不需要单独的/search/区域来执行搜索,我认为将搜索条件直接应用于集合资源会更干净:

/people?ssn=123456-7890  (people with SSN matching/containing "123456-7890")
/people?name=morgan      (people who's name is/contains "Morgan")

我有类似的东西,但只使用第一个字母作为过滤器:

/sites?alpha=f

列出所有以 F 开头的网站。您可以将其视为过滤器或搜索条件,这些术语只是同一枚硬币的不同方面。

于 2013-02-11T16:26:11.890 回答
3

很高兴看到有人花时间考虑他们的资源网址!

我会制作一个具有唯一 id 的 Url,以便为单个用户提供资源。喜欢:

http://api.mysite.com/person/12/

其中 12 是您的唯一 ID。请注意,我也更喜欢单数的“人”......

无论如何,网址应该返回:

{
  "ssn":  "840212-3312"
  "name": "Morgan"
  "id": "12"
}

但是,我还将创建一个通用搜索 URL,它返回与参数匹配的用户列表(json 数组或您需要的任何格式)。您可以将搜索参数指定为 get params,如下所示:

 http://api.mysite.com/person/search/?ssn=840212-3312

或者

 http://api.mysite.com/person/search/?name=Morgan

这些将针对单个搜索命中返回类似的内容-注意它是一个数组,而不是像直接指向单个用户的唯一 id url 这样的单个项目。

[{
  "ssn":  "840212-3312"
  "name": "Morgan"
  "id": "12"
}]

该搜索随后可以针对其他搜索条件进行扩充。您可能只能通过搜索网址返回唯一 ID——一旦您从搜索中获得唯一 ID 网址,您始终可以向其发出请求...

于 2013-02-11T15:44:28.743 回答
1

我建议你两者都不要使用。生成对 API 的单个用户和所有其他资源(包括其他用户的资源)唯一的资源 ID。

出于几个原因,使用唯一的数据库 ID 并不理想。首先,API 资源和数据库记录不一定总是一对一的,即使您现在已经这样设计了。其次,您可能会更改为生成不同格式唯一 ID 的不同数据存储。

此外,最好将 ID 与其他资源属性(例如 SSN)分开(顺便说一句,我希望您以非常安全的方式存储 SSN,但这是另一个主题)。如果出于某种原因,SSN 发生了变化,多个 API 资源与同一个 SSN 相关联,或者您决定某天不需要该数据,您不想更改 ID。

一种模式是在唯一 ID 前面加上一些指示资源类型的字符。例如,如果 User 是您 API 中的资源类型,则生成的唯一 ID 将类似于USR56382.

于 2014-07-18T21:19:21.437 回答
0

RESTful API 是一种强调以资源为中心的设计方法的架构风格。

在我看来,我会将资源保持为复数和名词格式。

每个资源,例如客户,都有以下统一的接口

POST /customers - 用于创建资源实例 PUT /customers/{customerId} - 用于更新特定实例 GET /customers - 用于搜索客户。所以@Ray,搜索不需要是URI本身的一部分。任何需要支持的过滤器或查询参数都应该存在。GET /customers/{customerId} - 检索客户的特定实例 DELETE /customers/{customerId} 删除特定实例

之所以复数,是因为它的行为就像一个工厂。例如,当您尝试创建资源的新实例时,该实例不存在,因此它不能位于自身实例上。因此,不使用奇异性。它还与搜索/查询密切相关,您不知道或持有资源的实际实例。因此,非常推荐使用复数形式。

现在,问题是资源 id 使用什么 - 数据库主键、生成的标识符或加密的令牌。

在我看来,数据库主键不应该暴露。资源标识符不应与数据库主键一一对应。但是,它发生了很多。更建议使用生成的基于 UUID 的密钥来避免任何连续的后续攻击,但世界并不总是理想的。

回到令牌或加密令牌,是敏感 API 的推荐方法,并且在两个单独的应用程序之间执行数据交换。如果我们使用它,加密/解密应该完全在 API 端。这意味着,子资源的加密密钥应作为父 API 响应的一部分返回,否则将达不到目的。

于 2021-09-14T22:14:07.607 回答