在我们的 Web 应用程序中,我们希望随机化记录 ID。原因是我们想隐藏数据库中已经有多少条目并且我们有未列出的东西。如果 ID 是简单的递增数字,则很容易猜出未列出事物的 ID。
在我看来,有三种方法可以做到这一点:
简单随机数
算法:
- 在插入时创建一个随机数。
- 检查 ID 是否已在使用中。如果是,请转到 1。
- 使用此 ID。
临
- 简单的
- 适用于任何大小或类型的 ID(32 位、64 位、可变长度、字符串)
魂斗罗
- 需要针对可能的竞争条件进行事务处理(算法不是原子的)
UUID
临
- 碰撞的可能性很低,你可以忽略它
魂斗罗
- 我们希望将页面标题作为 URL 注释 (
"#{id}--#{page_title}
) 的短 URL,UUID 会将此注释一直向右移动 - 我猜 UUID 作为主键的连接性能会降低吗?
加密的 ID
算法:
nextval
使用(原子!)从序列中读取数字- 使用密钥和适用于 ID 大小的加密算法加密 ID
临
- 没有竞争条件(不需要交易)
魂斗罗
- ID 列的大小永远不能改变
- 如果有人能破解/猜出钥匙,一切都是徒劳的
时间戳
由@emboss 推荐
临
- 简单的
- 不会用完 ID
魂斗罗
- 可能会产生碰撞(尽管需要测试它是否真的发生)
- 也许有点猜不透
随机公共 ID/基于姓名的公共 ID
由@viktor tron 推荐
URL 中出现的所有事物的第二个 ID,仅用于查找记录。使用内部普通 ID(用于连接等)。
临
- 内部一切都保持清醒
- 一个好的随机算法/命名方案应该使 URL 猜测变得不可能(足够)
魂斗罗
- 更改了很多在公共接口中使用 ID 的东西
- 用户可能希望他们可以减少包含此类标题的 URL,但在这种情况下,这些 URL 将不再有效
我想我会使用第三个选项。还是有更多的反对意见?有没有更好的解决方案?我们使用 Ruby on Rails 3.x 和 PostgreSQL 9.x。
编辑:未列出并不意味着私有!这意味着就像 YouTube 上的未列出的视频。它们是普通视频,只是没有在搜索或上传者的个人资料中列出。因此,您无法真正找到它们(无需尝试所有可能的 ID),但知道 URL 的每个人都可以访问它们。当然,将某些内容设为未列出并将链接发送给其他人的用户必须意识到它可能不会保持未知状态(URL 可能会被传递,并且通过链接可能最终会出现在搜索引擎中)。
我们还有另一种选择将事情保密。这是两个不同的东西。(我认为假设每个人都知道“未列出”的含义是错误的。)