如果我有10,000个用户且主键是从1到10,000的唯一ID,是否有办法为它们提供所有唯一ID,以便无法从中推断出原始主键?
例如,链接到您的Facebook个人资料或类似信息将是http://site.com/profile?id=293852
那里的id是否可能与数据库中用户的主键相同?我正在努力想办法找到两个不相关的唯一ID列,因为随机生成的列必须是唯一的。我想如果有可能使用数字的GUID只有长度会太长。
和想法?
答案 0 :(得分:2)
出于安全原因,确实建议使ID不顺序,以避免在系统中枚举用户。但是40亿(我的意思是2 ^ 32)太小而不能提供不可发现的间隔。这就是为什么GUID更可取的原因。根据数据库(查看您的规范,看起来像MSSQL),您可以存储在类guid字段,字节字段(对于MySQL)或2个单独的int64。
要减小URL大小,可以应用base64编码,以便GUID看起来更短。
答案 1 :(得分:2)
您通常有两种选择:
new Random(primaryKey).NextInt()
,或者它可能非常复杂,但可以防攻击,例如任何类型的Format-preserving encryption。但是......为什么你认为你应该保护主键的价值?如果唯一的原因是阻止用户猜测其他有效的用户ID,您只需将随机字符串附加到主键(并将其存储在数据库中并验证其访问的正确性)。
答案 2 :(得分:1)
如何生成随机和唯一ID是一个有用的问题 - 但您似乎在 生成它们时做出了假设!
我的观点是,您在创建行时不需要生成这些ID,因为它们基本上与所插入的数据无关。
我所做的是预先生成随机ID以供将来使用,这样我就可以享受自己的甜蜜时光并绝对保证它们是独一无二的,并且在插入时无需进行任何处理。
例如,我有一个带有order_id的订单表。当用户输入订单时,会立即生成此ID,永久递增1,2,3等。用户无需查看此内部ID。
然后我有另一个表 - random_ids(order_id,random_id)。我有一个每天晚上运行的例程,它预先加载了足够多的行,以覆盖可能在接下来的24小时内插入的订单。 (如果我在一天内获得10000份订单,我就会遇到问题 - 但这将是一个很好的问题!)
这种方法保证了唯一性,并且可以将任何处理负载从插入事务转移到批处理例程中,而不会影响用户。
答案 3 :(得分:0)
允许用户查看主键有什么问题?
您可以随机生成数字,确保它是一个非常大的数字,以便不太可能发生冲突,然后运行一个选择以检查它是否存在。
或者,你可以选择一个庞大的数字,然后围绕它做一些方程式。类似的东西:
unique = 1000000000 * (-1 * PK)^3
这意味着随着PK增加,唯一数字将远离您的起始数字,并且取决于PK是奇数还是偶数,高于或低于它。您添加到等式中的复杂性越高,发现它的可能性就越小,但永远不会100%依赖此方法,因为总有可能有人将其解决。
答案 4 :(得分:0)
我所做的是使用GUID的一部分和实际ID。
在表格中,我有一个列类型uniqueidentifier,默认值为newid()
然后我参与其中并在末尾添加实际的序列ID,并在它们之间使用已知的分隔符。我使用字母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的所有行,然后检查GUID列
如果人们试图猜测个人资料的ID,他们就不能只改变其中的一部分并取得成功。