【问题标题】:What method for random id's in web appWeb应用程序中随机ID的什么方法
【发布时间】:2011-07-25 17:39:15
【问题描述】:

我的网址如下所示:

http://domain.com/object/23/

我希望 23 不是连续的并且相当随机。我在 Stack Overflow 上看到过其他帖子问同样的问题,但我的要求与我所看到的有点不同。

我使用该网站的许多人都是竞争对手,他们很容易用一些数字来获取竞争信息。我这样做不是为了安全,我知道通过默默无闻的安全是浪费时间。我只是在寻找一种快速的方法来防止人们四处闲逛。

我正在使用带有 Postgres 数据库的 python/SQLAlchemy 执行此操作。我查看了 UUID 的主键,但它们似乎对性能造成了很大的影响,因为我有很多连接发生。我还可以在附加列中执行 UUID,然后根据顺序积分主键执行所有连接。

大多数需要此功能的表的记录数少于 1000 条。但是一张表会有几百万条记录。如果没有那个表,我只会使用 uuid 并完成它。但既然我这样做了,我真的不认为 uuid 是一个很好的选择。

真正的问题是我的其他选择是什么。

  1. 使用顺序数字主键,但在数据库外部使用一些轻量级算法动态加密/解密它们

  2. 分离列并在创建行时生成的 primary_key + secret_key 上使用 sha1 哈希(或其他哈希)。然后我可以通过这个哈希找到行,然后在正常的pk上做所有的连接。

性能是这里最重要的事情,同时仍然保持一定程度的随机性,碰撞的可能性很小。 #1的加密/解密的最佳选择是什么,或者#2的最佳哈希算法是什么。有没有比这两个更明显的方法?有几百万行 uuid 不会让我放慢速度,这就是解决方案?

【问题讨论】:

  • 它们似乎对性能造成了很大的影响”。你测试过这个假设吗?性能影响有多大?
  • 是什么让您认为生成 UUID 会影响性能?生成的成本基本上是生成一个随机 128 位数字的成本。比较这种大小的整数的成本可以忽略不计。
  • UUID 的随机性带来了性能损失:stackoverflow.com/a/1151733/23368

标签: postgresql sqlalchemy obfuscation uuid


【解决方案1】:

要从序列中生成唯一且外观随机的标识符,使用密码可能是一个好主意。由于它们的输出是双射的(输入值和输出值之间存在一对一的映射)——与散列不同,您将不会有任何冲突。这意味着您的标识符不必像哈希一样长。

大多数加密密码适用于 64 位或更大的块,但 PostgreSQL wiki 有一个适用于(32 位)int 类型的 example PL/pgSQL procedure for a "non-cryptographic" cipher 函数。免责声明:我自己没有尝试过使用此功能。

要将其用作主键,请从 wiki 页面运行 CREATE FUNCTION 调用,然后在 empty 表上执行:

ALTER TABLE foo ALTER COLUMN foo_id SET DEFAULT pseudo_encrypt(nextval('foo_foo_id_seq')::int);

瞧!

pg=> insert into foo (foo_id) values(default);
pg=> insert into foo (foo_id) values(default);
pg=> insert into foo (foo_id) values(default);
pg=> select * from foo;
  foo_id   
------------
 1241588087
 1500453386
 1755259484
(4 rows)

【讨论】:

    【解决方案2】:

    我会选择类似于您的选项 2 的方法:例如,将 HMAC 与 SHA1 结合使用,以生成一个哈希值,该哈希值可以针对每个请求进行验证,甚至无需靠近数据库。我经常制作这样的防篡改“票”。例如

    use Digest::HMAC_SHA1 qw(hmac_sha1_hex);
    $id = shift;
    print "$id.", substr(hmac_sha1_hex($id, "s3kr1t"), 0, 8), "\n"
    

    并验证:

    use Digest::HMAC_SHA1 qw(hmac_sha1_hex);
    $tkt = shift;
    ($id,$sum) = ($tkt =~ /(.+)\.([0-9a-f]+)/)
            or die "Invalid tkt (bad format): $tkt\n";
    $sum eq substr(hmac_sha1_hex($id, "s3kr1t"), 0, 8)
            or die "Invalid tkt (MAC mismatch): $tkt\n";
    print $id, "\n"
    

    这会为 id 23 生成“23.3b30e326”的“票证”。

    【讨论】:

      【解决方案3】:

      散列/加密对于您想要实现的目标来说似乎有些矫枉过正。一个单独的列如何存储 10000 到 99999(或 100000、999999 等)之间的随机数,然后链接如下:

      http://domain.com/object/23-74938/
      

      “74938”是随机位

      【讨论】:

        猜你喜欢
        • 2023-03-22
        • 1970-01-01
        • 2010-09-08
        • 2018-11-29
        • 2013-08-16
        • 2011-07-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多