restapi:隐藏代理键并只向用户公开自然键

icomxhvb  于 2021-08-13  发布在  Java
关注(0)|答案(3)|浏览(395)

假设我们使用的数据库具有以下关系:

CREATE TABLE Author (
  first_name VARCHAR NOT NULL,
  last_name VARCHAR NOT NULL,
  birth_date DATE NOT NULL,
  death_date DATE,
  biography TEXT,
  UNIQUE(first_name, last_name, birth_date)
);

在现实世界中,两个名字和姓氏相同的作者在同一天出生是极不可能的。因此,我们认为作者的名字、姓氏和出生日期的组合是一个自然的关键。
然而,为了连接表和创建外键,这有点痛苦,因为这意味着我们需要在表中一遍又一遍地存储这三条信息。也许我们有一个 BookAuthor 关联 Author s与 Book s。
因此,我们创建一个串行id(如果需要,也可以创建一个uuid)并将其作为主键:

CREATE TABLE Author (
  id SERIAL PRIMARY KEY,
  first_name VARCHAR NOT NULL,
  last_name VARCHAR NOT NULL,
  birth_date DATE NOT NULL,
  death_date DATE,
  biography TEXT,
  UNIQUE(first_name, last_name, birth_date)
);

然而,根据我在这里对stackoverflow和其他站点所做的阅读,似乎您永远不想向最终用户公开您的主键,因为这样做可能使他们能够确定他们不应该能够确定的信息。例如,如果这是一个涉及用户帐户的情况,而我们决定使用串行ID(我们不应该,但请原谅我),那么有人可能会计算出我们的数据库中总共有多少用户,这不是他们应该看到的信息。在这个特殊的例子中,有人知道我们有多少作者并不是什么大事。但我想遵循最佳实践。
所以,如果我要为这个数据库设计一个restapi,那么使用自然密钥来唯一地标识资源是可以接受的吗( Author s) 而不是使用序列号?例如: https://www.foo.bar/authors/?first=:Terry&last=Pratchett&dob=19480424 我在这里的理由是,最终用户没有办法知道与作者对应的序列号,以便查询它们。

wbrvyc0a

wbrvyc0a1#

只要您保证数据元素的这种组合是唯一的备用键(最好有一个数据库唯一键来实现这一点),并且在所有api方法中一致地使用它,那么使用它来标识restapi中的资源是完全可以接受的。这里面没有概念上的缺陷。
唯一的小问题是,如果更改自然密钥、更新姓名或出生日期,缓存的数据将无效。没什么大不了的。get方法仍然是幂等的。
如果选择使用自然键作为标识符,并且该键的数据元素是可编辑的,请记住,在放置更新并希望继续显示同一资源时,可能需要重定向到新的url。

kcwpcxri

kcwpcxri2#

为了解决你所关注的不同问题,我建议如下:
如果可能,生成一个顺序id(数字序列),它将是您的主键。此密钥用于内部应用程序使用(或db internal),并且从不离开后端。
唯一(非数字)id(uuid?。。。或者来自id+first\u name+las\u name+b\u day)的散列,它将用作通过api调用访问数据的密钥。
或者,您仍然可以拥有唯一键:first\u name+last\u name+b\u day。
这样,您的数据库就有了一个简单的顺序id,但也有一个不公开系统相关信息的id。
这也许不是一个完美或完整的解决方案,但可能是一个良好的开端。

au9on6nz

au9on6nz3#

所以,如果我要为这个数据库设计一个restapi,那么使用自然密钥来唯一地标识资源(作者)而不是使用串行id是可以接受的吗?
你的问题的简短答案是否定的。
较长的答案是,这里实际上有两个不同的关注点;你提到:
最终用户不可能知道该作者对应的序列号,以便查询它们。
这意味着您希望最终用户能够搜索作者。
这与 GET 路由,它显式要求请求者知道唯一标识符(请阅读此w3对基本rest方法的描述以获取更多信息)。
我建议您有两个独立的api,一个用于检索给定uuid的资源的所有详细信息,另一个用于按某些字段进行搜索。

相关问题