简体   繁体   English

如何在不使用数据库中的主键的情况下为用户提供唯一的ID?

[英]How do you give your users a unique ID without using the primary key in the database?

If I have 10,000 users and the primary key is a unique ID going from 1 to 10,000, is there a way to give them all a unique ID such that the original primary key cannot be inferred from it? 如果我有10,000个用户,并且主键是从1到10,000的唯一ID,是否可以为他们提供所有唯一ID,从而无法从中推导出原始主键?

For example, linking to your facebook profile or similar would be http://site.com/profile?id=293852 例如,链接到您的Facebook个人资料或类似内容将为http://site.com/profile?id=293852

Is it likely that the id there is the same as the primary key of their user in the database? ID是否可能与数据库中其用户的主键相同? I am struggling to think of a way to have two unrelated unique ID columns, because randomly generated ones would have to be unique. 我正在努力想办法拥有两个不相关的唯一ID列,因为随机生成的列必须是唯一的。 I imagine if it were possible to have a GUID using numbers only the length would be far too long. 我想如果有可能使用数字的GUID,则长度将太长。

And ideas? 有想法吗?

It is really recommends in security reason to make ID non sequential, to avoid enumerating of user in system. 出于安全原因,确实建议使ID不连续,以免枚举系统中的用户。 But 4 billions (I mean 2^32) is too small to provide non-discoverable interval. 但是40亿(我的意思是2 ^ 32)太小,无法提供不可发现的间隔。 That is why GUID is more preferable. 这就是为什么GUID更可取的原因。 Depending on database (looking at your spec it seems like MSSQL) you can store in guid-like fields, byte fields (for MySQL) or 2 separate int64. 根据数据库(在您的规范中看起来像MSSQL),您可以将其存储在类似guid的字段,字节字段(对于MySQL)或2个单独的int64中。

To reduce URL size the base64 encoding can be applied so GUID looks shorter. 为了减小URL的大小,可以应用base64编码,因此GUID看起来更短。

You have generally two options: 通常,您有两种选择:

  1. As you said, use randomly generated data. 如您所说,请使用随机生成的数据。 (You only need to ensure they are unique, ie either long enough, or generate-verify-retry.) (您只需要确保它们是唯一的即可,即足够长的时间,或生成-verify-retry。)
  2. Get the primary key and transform it “pseudorandomly” to something else which seems to have nothing to do with the primary key. 获取主键并将其转换“伪随机”到别的东西,这似乎什么都没有做的主键。 The transformation might be very simple (if you want just a mild protection), eg new Random(primaryKey).NextInt() , or it might be quite complicated, but attack-proof, eg any kind of Format-preserving encryption . 转换可能非常简单(如果您只需要一个轻微的保护),例如new Random(primaryKey).NextInt() ,也可能非常复杂,但是可以防止攻击,例如任何形式的格式保留加密

But then… why do you think you should protect the values of your primary keys? 但是,然后……为什么您认为应该保护主键的值? If the only reason is to prevent users guessing other valid user IDs, you can just append a random string to the primary key (and store it in the database and verify its correctness on access). 如果唯一的原因是防止用户猜测其他有效的用户ID,则可以将随机字符串附加到主键(并将其存储在数据库中,并在访问时验证其正确性)。

How you generate the random and unique ids is a useful question - but you seem to be making an assumption about when to generate them! 如何生成随机和唯一ID是一个有用的问题-但是您似乎在假设何时生成它们!

My point is that you do not need to generate these id's at the time of creating your rows, because they are essentially independent of the data being inserted. 我的观点是,在创建行时无需生成这些ID,因为它们实际上与所插入的数据无关。

What I do is pre-generate random id's for future use, that way I can take my own sweet time and absolutely guarantee they are unique, and there's no processing to be done at the time of the insert. 我要做的是预先生成随机ID供将来使用,这样我就可以享受自己的美好时光,并绝对保证它们是唯一的,并且在插入时无需进行任何处理。

For example I have an orders table with order_id in it. 例如,我有一个带有order_id的订单表。 This id is generated on the fly when the user enters the order, incrementally 1,2,3 etc forever. 当用户输入订单时,此ID会即时生成,并永久递增1,2,3等。 The user does not need to see this internal id. 用户不需要查看此内部ID。

Then I have another table - random_ids with (order_id, random_id). 然后我有另一个表-(order_id,random_id)的random_ids。 I have a routine that runs every night which pre-loads this table with enough rows to more than cover the orders that might be inserted in the next 24 hours. 我有一个例程每天晚上运行,该例程会在此表中预加载足够的行,以覆盖以后24小时内可能插入的订单。 (If I ever get 10000 orders in one day I'll have a problem - but that would be a good problem to have!) (如果一天之内能收到10000个订单,我会遇到问题-但这是一个好问题!)

This approach guarantees uniqueness and takes any processing load away from the insert transaction and into the batch routine, where it does not affect the user. 这种方法可以保证唯一性,并且可以将处理事务从插入事务转移到批处理例程中,而不会影响用户。

What's wrong with allowing the user to see the primary key? 允许用户看到主键有什么问题?

You could generate the numbers randomly, make sure it's a really big number so that clashes are unlikely, then just run a select to check it doesn't exist. 您可以随机生成数字,确保它是一个非常大的数字,以免发生冲突,然后只需运行一次select来检查它是否不存在。

Or, you could pick a huge number, and then base some equation around that. 或者,您可以选择一个巨大的数字,然后根据该方程建立一些方程式。 Something like: 就像是:

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

That means that the unique numbers will get further away from your starting number as the PK increases, and be above or below it depending on whether the PK is odd or even. 这意味着,随着PK的增加,唯一编号将与您的起始编号相距更远,并且取决于PK是奇数还是偶数,该唯一编号将在其之上或之下。 The more complexity you add to the equation, the less likely it'll be discovered, but never ever 100% rely on this method, as there is always the possibility someone will work it out. 添加到方程式中的复杂度越高,被发现的可能性就越小,但是永远不会100%依赖于此方法,因为总有可能有人会解决它。

What I do is use part of a GUID and the actual ID. 我要做的是使用GUID和实际ID的一部分。

In the table I have a column type uniqueidentifier with a default value of newid() 在表中,我有一个列类型的uniqueidentifier,其默认值为newid()

I then take part of it and add the actual serial ID on the end with a known delimiter between them. 然后,我参与其中,并在末尾添加实际的序列ID,并在它们之间使用已知的定界符。 I use the letter H as this doesn't appear in GUIDs. 我使用字母H,因为它没有出现在GUID中。

So for row #8659 I would have: 因此,对于第8659行,我将有:
IDcolumn=8659 IDcolumn = 8659
GUIDcolumn='{200BAB55-C7D5-4456-AB57-CFF8B7E82A90}' GUIDcolumn = '{200BAB55-C7D5-4456-AB57-CFF8B7E82A90}'
PROFILECODE='200BAB55H8659' PROFILECODE = '200BAB55H8659'

I can locate the correct row by: 我可以通过以下方式找到正确的行:

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';

In theory the SQL parser should find all rows with IDcolumn 8659 first and then check for the GUIDcolumn 从理论上讲,SQL解析器应首先查找IDcolumn 8659的所有行,然后检查GUIDcolumn

If people try to guess an ID for a profile they couldn't just change one part of it and succeed. 如果人们试图猜测个人资料的ID,他们就不能仅仅更改其中一部分就可以成功。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用实体框架LINQ将唯一主键插入数据库 - Insert Unique Primary Key into Database using Entity-Framework LINQ 您如何/如何保护您的用户详细信息 - How would/do you secure your users details 如何通过代码生成新的主键ID? - How do I generate a new Primary Key ID through code? 如何使用HTTP POST为SQL数据库设置正确的主键? - How to set the correct primary key to a SQL database using HTTP POST? 如何使用ASP.NET项目部署SQL 2005 Express数据库的BLANK副本? - How do you deploy a BLANK copy of your SQL 2005 express database with your ASP.NET project? 您在哪里存储数据库连接字符串? - Where do you store your database connectionstring? 您是否将虚拟机用作主要开发环境? - Are you using virtual machine as your primary development environment? 主键必须使用EFCode称为“ Id”吗? - Primary key has to be called “Id” using EFCode? 如何将一个具有公共ID(主键)的用户的多行插入SQL Server数据库? - How to insert multiple rows of one user with common ID (primary key) into SQL Server database? 如何在没有ID的情况下在div上自动生成点击? - How do you generate an automatic click on a div without having an ID for it?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM