【问题标题】:How predictable is NEWSEQUENTIALID?NEWSEQUENTIALID 的可预测性如何?
【发布时间】:2014-06-11 08:29:38
【问题描述】:

根据Microsoft's documentation on NEWSEQUENTIALID,NEWSEQUENTIALID 的输出是可预测的。但是可预测性如何?假设我有一个由NEWSEQUENTIALID 生成的 GUID,这有多难:

  • 计算下一个值?
  • 计算前一个值?
  • 计算第一个值?
  • 即使根本不知道任何 GUID,也要计算第一个值?
  • 计算行数?例如。当使用整数时,/order?id=842 告诉我应用程序中有 842 个订单。

以下是一些关于我正在做什么以及各种权衡的背景信息。

使用 GUID 而非整数作为主键的安全性好处之一是 GUID 很难猜测。例如。假设黑客看到像/user?id=845 这样的URL,他可能会尝试访问/user?id=0,因为数据库中的第一个用户很可能是管理用户。此外,黑客可以遍历/user?id=0..1..2 以快速收集所有用户。

同样,整数的一个隐私缺点是它们会泄露信息。 /order?id=482 告诉我,该网店自实施以来已有 482 个订单。

不幸的是,使用 GUID 作为主键具有众所周知的性能缺点。为此,SQL Server 引入了NEWSEQUENTIALID 函数。在这个问题中,我想了解NEWSEQUENTIALID 的输出的可预测性。

【问题讨论】:

    标签: sql sql-server primary-key guid newsequentialid


    【解决方案1】:

    在大多数情况下,下一个newsequentialid 可以通过获取当前值并将一个添加到第一个十六进制对来预测。

    换句话说:

    1E29E599-45F1-E311-80CA-00155D008B1C

    后面是

    1F29E599-45F1-E311-80CA-00155D008B1C

    后面是

    2029E599-45F1-E311-80CA-00155D008B1C

    有时,序列会从一个新值重新开始。

    所以,这是非常可预测的

    NewSequentialID是windows函数UuidCreateSequential的包装器

    【讨论】:

    • 我在我的数据库中观察到了类似的行为。一系列行似乎遵循一种模式,但随后突然跳转到一个新值。这个新值也能猜到吗?
    【解决方案2】:

    底层操作系统函数是UuidCreateSequential。该值来自您的网卡 MAC 地址之一和per-os-boot incremental value。见RFC4122。 SQL Server 做了一些byte-shuffling 以使结果正确排序。因此,从某种意义上说,价值是高度可预测的。具体来说,如果您知道一个值,您可以立即预测一个相似值的范围。

    但是,我们无法预测 id=0 的等价物,也无法预测 52DE358F-45F1-E311-93EA-00269E58F20D 意味着商店至少售出了 482 件商品。

    唯一“批准”的随机生成是 CRYPT_GEN_RANDOM(包装了 CryptGenRandom),但这显然是一个糟糕的关键候选。

    【讨论】:

    • 优秀而彻底的回应!
    【解决方案3】:

    你可以试试这个代码:

    DECLARE @tbl TABLE (
        PK uniqueidentifier DEFAULT NEWSEQUENTIALID(),
        Num int
    )
    INSERT INTO @tbl(Num) values(1),(2),(3),(4),(5)
    select * from @tbl
    

    这次在我的机器上是结果:

    PK                                      Num
    52DE358F-45F1-E311-93EA-00269E58F20D    1
    53DE358F-45F1-E311-93EA-00269E58F20D    2
    54DE358F-45F1-E311-93EA-00269E58F20D    3
    55DE358F-45F1-E311-93EA-00269E58F20D    4
    56DE358F-45F1-E311-93EA-00269E58F20D    5
    

    您应该在不同的时间/日期尝试多次以插入行为。 我试过它运行了几次,第一部分每次都在变化(你在结果中看到:52...,53...,54...,等等...)。我等了一段时间检查它,一段时间后第二部分也增加了。我想这会持续到所有部分。基本上它看起来就像简单的+=1 incementation 转换为 Guid。

    编辑:

    如果您想要顺序 GUID 并且想要控制这些值,您可以使用 Sequences

    示例代码:

    select cast(cast(next value for [dbo].[MySequence] as varbinary(max)) as uniqueidentifier)
    

    【讨论】:

    • 那有什么用呢?为什么不直接使用 1,2,3,4,5?
    【解决方案4】:

    • 计算下一个值?是的

    微软说:

    如果担心隐私问题,请勿使用此功能。可以猜测下一个生成的 GUID 的值,从而访问与该 GUID 关联的数据。

    所以有可能获得下一个值。如果有可能获得prevoius,我找不到信息。

    来自:http://msdn.microsoft.com/en-us/library/ms189786.aspx

    编辑:关于 NEWSEQUENTIALID 和安全性的另外几句话:http://vadivel.blogspot.com/2007/09/newid-vs-newsequentialid.html

    编辑: NewSequentialID 包含服务器的 MAC 地址(或其中一个),因此知道顺序 ID 会为潜在的攻击者提供信息,这些信息可能对安全或 DoS 攻击有用。 来自:Are there any downsides to using NewSequentialID?

    【讨论】:

    • 感谢您的回复。我知道 NEWSEQUENTIALID 是可以预测的。在这个问题中,我想了解如何可预测。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-27
    • 1970-01-01
    • 2018-05-16
    • 2014-07-07
    • 2015-08-09
    • 1970-01-01
    相关资源
    最近更新 更多