Web应用程序中随机ID的方法

时间:2011-03-30 00:37:49

标签: postgresql sqlalchemy obfuscation uuid

我的网址如下:

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

我更希望23不顺序且相当随机。我已经看到Stack Overflow上的其他帖子可能会问同样的事情,但我的要求与我看到的有点不同。

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

我正在使用带有Postgres数据库的python / SQLAlchemy。我看过UUIDs的主键,但是由于我有很多连接发生,它们似乎是一个很大的性能影响。我还可以在一个附加列中执行UUID,然后根据顺序积分主键执行所有连接。

大多数需要此表的表的记录少于1000条。但是1个表会有几百万个记录。如果没有那张桌子,我只会使用uuid并完成它。但是,自从我这样做以来,我并不认为uuid是一个很好的选择。

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

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

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

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

3 个答案:

答案 0 :(得分:2)

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

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

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

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)

答案 1 :(得分:1)

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

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

其中'74938'是随机位

答案 2 :(得分:1)

我会选择类似你的选项2:例如,使用HMAC和SHA1来生成一个哈希值,可以为每个请求验证,甚至不需要靠近数据库。我经常生产这样的防篡改“门票”。 e.g。

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”的“票证”。