在 REST API 中向客户端公开数据库 ID 是一种不好的做法吗?

Kas*_*per 15 security rest

在我的职业生涯中,我有过几次这样的讨论。在我看来,在 REST API 响应中将存储在数据库中的 id 公开给客户端是完全可以的。但与我共事过的一些人认为这确实是安全方面的第一课:“永远不要将您的数据库 ID 暴露给客户端。”

然后他们带着各种复杂性来避免这种情况。例如,在一项工作中,我必须对其余响应中的每个 ID 进行散列,然后对请求中的所有 ID 进行散列。

现在在我的新工作中,我们有以下模式。一个表有一个自动递增的“id”,但我们不公开它,旁边有一个 uuid“代码”,这是我们向客户端公开的。所以本质上我们有 2 个 id,都存储在数据库中,但一个我们可以公开,另一个我们可以,因为:

“永远不要向客户端公开您的数据库 ID。”

这甚至有点道理吗?我们仍然向客户端公开一个“标识符”。如果问题是有人可以看到我们在表中有多少行,因为“id”是自动递增的,我只会将“id”设为 uuid,并将其公开给客户端。

如果您查看其他公共休息 API 的示例,在我看来它们总是公开数据库 ID,没有问题。例如,gitlab:

GET /projects/:id/users

[
  {
    "id": 1,
    "username": "john_smith",
    "name": "John Smith",
    "state": "active",
    "avatar_url": "http://localhost:3000/uploads/user/avatar/1/cd8.jpeg",
    "web_url": "http://localhost:3000/john_smith"
  },
  {
    "id": 2,
    "username": "jack_smith",
    "name": "Jack Smith",
    "state": "blocked",
    "avatar_url": "http://gravatar.com/../e32131cd8.jpeg",
    "web_url": "http://localhost:3000/jack_smith"
  }
]
Run Code Online (Sandbox Code Playgroud)

推特: https://api.twitter.com/1.1/statuses/show.json?id={id}

但即使是stackoverflow: /sf/{id} https://stackoverflow.com/users/{id}

我敢打赌,2188707在 url/sf/users/153209521/中只是我在 stackoverflow 数据库中的用户 ID。

Aba*_*666 9

我没有看到在您的 API 中公开纯数据库 ID 的任何安全原因。如果您的数据库暴露了,您无论如何都丢失了。通过默默无闻来确保安全永远不是解决方案。

但是,还有一些其他原因需要考虑:

  • 公开数据库 ID 会创建与数据库的耦合。想象一下合并来自不同数据库的数据(共享相同的架构),或者将备份数据应用到已经在使用的数据库中。不能保证相同的 ID 仍然可用。

  • 设计一个合适的基于资源的 API 需要你公开通用唯一 ID (UUID) 或技术复合键,原因很简单,没有其他方法可以确保不同系统/数据库的唯一性。

  • 如果您提供在租户之间共享表(歧视列)的多租户服务,并且路径中的 ID 是表的主键,因此它与该表中的数量或行成比例增加,那么您将暴露向不应该知道这一点的客户提供有关该业务增长的信息。是的,当然经常谁在乎..但你必须知道你违反了信息隐藏并决定它是否可以接受。 (3认同)
  • 根据我的经验,一旦你开放 SQL 注入,你几乎就可以迭代整个数据库。您是否有一个实际上仅在有 id 可用时才有效的示例?接下来我想强调的是,我反对在 REST API 中使用数据库标识符。只是出于不同的原因。 (2认同)

San*_*ños 9

顺序主键存在一些问题:

  1. 它们显示您的数量(例如:如果您创建一个对象并且 API 返回 ID 10,001,它会粗略估计您的数据库上有多少该类型的对象,这可能会让黑客或竞争对手感兴趣)
  2. 黑客可以利用“不安全的直接对象引用”(链接
  3. 黑客可以利用它进行 XSS 攻击(链接

来源:改编自 Django 1.11 的两勺


M.E*_*ady 8

不是安全问题,但它让用户知道一些有关您公司数据大小的信息。并且有些公司不喜欢公开此类信息