【问题标题】:How do you give your users a unique ID without using the primary key in the database?如何在不使用数据库主键的情况下为用户提供唯一 ID?
【发布时间】:2011-06-26 20:20:40
【问题描述】:

如果我有 10,000 个用户,并且主键是一个从 1 到 10,000 的唯一 ID,有没有办法给他们一个唯一 ID,这样就无法从中推断出原始主键?

例如,链接到您的 facebook 个人资料或类似内容将是 http://site.com/profile?id=293852

那里的id可能与数据库中用户的主键相同吗?我正在努力想办法让两个不相关的唯一 ID 列,因为随机生成的必须是唯一的。我想如果有可能只有使用数字的 GUID 长度会太长。

还有什么想法?

【问题讨论】:

  • 主键/ID可见有问题吗?
  • 你能创建一个主键的哈希值并分发出去吗?
  • @Scorpi0:我不确定,你认为是吗?你认为你的 facebook id 在 profile 之后吗?id= 是你的主键吗?
  • 在 ICQ 中我认为是 ID...问题是:您想知道 facebook 是如何完成的,还是您真的需要这个功能?
  • @Scorpi0:如果 facebook 只使用主键,我就不用担心隐藏这么多。我认为这是一种相当简单的方法来判断我应该在自己的网站上采用哪种方式。

标签: asp.net sql unique-index


【解决方案1】:

出于安全原因,确实建议使 ID 不连续,以避免在系统中枚举用户。但是 40 亿(我的意思是 2^32)太小,无法提供不可发现的间隔。这就是为什么 GUID 更可取的原因。根据数据库(看您的规范,它看起来像 MSSQL),您可以存储在类似 guid 的字段、字节字段(对于 MySQL)或 2 个单独的 int64 中。

为了减小 URL 大小,可以应用 base64 编码,这样 GUID 看起来更短。

【讨论】:

    【解决方案2】:

    允许用户看到主键有什么问题?

    您可以随机生成数字,确保它是一个非常大的数字以便不太可能发生冲突,然后只需运行一个选择以检查它不存在。

    或者,您可以选择一个巨大的数字,然后围绕它建立一些方程式。比如:

    unique = 1000000000 * (-1 * PK)^3
    

    这意味着随着 PK 的增加,唯一编号将远离您的起始编号,并根据 PK 是奇数还是偶数而高于或低于它。方程越复杂,被发现的可能性就越小,但永远不要 100% 依赖这种方法,因为总有可能有人会解决它。

    【讨论】:

      【解决方案3】:

      您通常有两种选择:

      1. 如您所说,使用随机生成的数据。 (您只需要确保它们是唯一的,即足够长,或者生成-验证-重试。)
      2. 获取主键并将其“伪随机”转换为其他似乎与主键无关的东西。转换可能非常简单(如果您只想要温和的保护),例如new Random(primaryKey).NextInt(),或者它可能非常复杂,但可以防止攻击,例如任何类型的Format-preserving encryption

      但是……为什么您认为应该保护主键的值?如果唯一的原因是为了防止用户猜测其他有效的用户 ID,您可以将一个随机字符串附加到主键(并将其存储在数据库中并在访问时验证其正确性)。

      【讨论】:

      • 我喜欢最后一部分,这很聪明!
      【解决方案4】:

      我所做的是使用部分 GUID 和实际 ID。

      在表中,我有一个列类型 uniqueidentifier,默认值为 newid()

      然后我参与其中并在末尾添加实际的序列号,并在它们之间添加一个已知的分隔符。我使用字母 H,因为它不会出现在 GUID 中。

      所以对于第 8659 行,我会:
      IDcolumn=8659
      GUIDcolumn='{200BAB55-C7D5-4456-AB57-CFF8B7E82A90}'
      PROFILECODE='200BAB55H8659'

      我可以通过以下方式找到正确的行:

      partGUID=split(PROFILECODE,'H')(0) - gives 200BAB55
      realID=split(PROFILECODE,'H')(1) - give 8659
      select * from mytable where IDcolumn=8659 and left(GUIDcolumn,8)='200BAB55';
      

      理论上,SQL 解析器应该首先找到 IDcolumn 为 8659 的所有行,然后检查 GUIDcolumn

      如果人们试图猜测个人资料的 ID,他们不可能只更改其中的一部分并成功。

      【讨论】:

        【解决方案5】:

        如何生成随机且唯一的 id 是一个有用的问题 - 但您似乎在假设 何时 生成它们!

        我的观点是,您不需要在创建行时生成这些 id,因为它们本质上独立于插入的数据。

        我所做的是预先生成随机 id 以供将来使用,这样我就可以度过自己的美好时光并绝对保证它们是独一无二的,并且在插入时无需进行任何处理。

        例如,我有一个带有 order_id 的订单表。当用户输入订单时,此 id 会即时生成,以 1、2、3 等永远递增。用户不需要看到这个内部 id。

        然后我有另一个表-带有(order_id,random_id)的random_ids。我有一个每天晚上运行的例程,它预先加载这个表有足够的行来覆盖未来 24 小时内可能插入的订单。 (如果我在一天内收到 10000 个订单,我会遇到问题 - 但那将是一个很好的问题!)

        这种方法保证了唯一性,并将任何处理负载从插入事务转移到批处理例程中,不会影响用户。

        【讨论】:

          猜你喜欢
          • 2018-03-05
          • 1970-01-01
          • 2013-10-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多