随机化DB记录ID

pan*_*nzi 5 random encryption postgresql uuid ruby-on-rails

在我们的Web应用程序中,我们希望随机化记录ID.原因是我们想要隐藏数据库中已有多少条目,我们有未列出的内容.如果ID是简单的增量数字,则很容易猜出未列出的内容的ID.

我认为有三种方法可以做到这一点:

简单的随机数

算法:

  1. 在插入时创建一个随机数.
  2. 检查ID是否已被使用.如果是,转到1.
  3. 使用此ID.

  • 简单
  • 适用于任何大小或类型的ID(32位,64位,变长,字符串)

反对

  • 需要针对可能的竞争条件进行交易(算法不是原子的)

的UUID

  • 碰撞的可能性非常低,你可以忽略它

反对

  • 我们希望有一个很好的短网址,页面标题为URL comment("#{id}--#{page_title}),UUID会将此评论一直移到右边
  • 我猜UUID作为主键会在连接上有较低的性能吗?

加密的ID

算法:

  1. 使用nextval(原子!)读取序列中的数字
  2. 使用密钥和加密算法加密ID,加密算法使用ID的大小

  • 没有竞争条件(不需要交易)

反对

  • ID列的大小永远不能更改
  • 如果有人可以破解/猜测密钥都是无用的

时间戳

由@emboss推荐

  • 简单
  • 不会用完ID

反对

  • 可能会产生碰撞(虽然需要测试它是否真的发生)
  • 也许有些可猜测

随机公共ID /基于名称的公共ID

由@viktor tron推荐

URL中出现的所有内容的第二个ID,仅用于查找记录.使用内部正常ID(用于连接等).

  • 内部一切都保持清醒
  • 一个好的随机算法/命名方案应该让URL猜测不可能(足够)

反对

  • 改变很多在公共接口中使用ID的东西
  • 用户可能希望他们可以删除带有此类标题的网址,但在这种情况下,网址将不再有效

我想我会使用第三种选择.还是有更多反对它的论据?有更好的解决方案吗?我们使用Ruby on Rails 3.x和PostgreSQL 9.x.

编辑:不公开并不代表私人!它就像YouTube上的不公开视频一样.它们是普通视频,未在搜索或上传者的个人资料中列出.所以你无法真正找到它们(没有尝试所有可能的ID),但知道URL的每个人都可以访问它们.当然,制作未列出的内容并将链接发送给其他人的用户必须知道它可能不会保持未知(URL可能会被传递并且通过链接可能最终会出现在搜索引擎中).

我们还有另一种选择,可以将事物设为私有.这是两件不同的事情.(我认为假设每个人都知道"未上市"意味着什么是错误.)

Ser*_*sev 12

这是错误解决问题的错误方法.

您认为问题是:用户可以猜测"未列出"事物的ID并使用它们.

实际问题是:用户可以未经授权访问.

将授权逻辑放在适当的位置,允许用户只访问他可以合法访问的项目,并禁止其他所有内容.

隐藏数据库中有多少条目

如果这是原因,我认为小的并不羞耻.无论如何,你可以从100000开始你的序列或增加N或使用另一个类似的技巧:)

  • 是的; +1,比我的评论更好的解释.但根据我的垃圾邮件文件夹,小*有*羞耻. (2认同)

Vik*_*rón 3

我建议采用一种完全不同的方式:根本不向用户显示记录 ID。你不需要。使用另一种形式的 url 标识。

既然你说你想要漂亮的网址,你可以简单地使用 slugger/permalink gem,比如https://github.com/norman/friend_id

Friendly_id 的默认 slug 生成器提供了检查 slug 字符串的唯一性的功能,并在必要时附加一个序列来保证它。

说真的,别管ID了:)