用户ID混淆

我希望之前有人问这个问题,但在这里没有找到合适的答案,也没有时间提出我自己的解决方案……

如果我们有一个带有int identity主键的用户表,那么我们的用户在站点上注册时会有连续的ID。

我们在网站url上有用户公开个人资料页面:

 www.somesite.com/user/1234 

其中1234是实际的用户ID。 没有什么容易看到用户的ID 本身 ,但它确实让任何人都能够检查我的网站上注册了多少用户…手动增加这个数字最终会让我找到无效的个人资料。

这是我将可逆ID映射到具有固定长度的看似随机数的主要原因:

 www.somesite.com/user/6123978458176573 

你能指点我做一个这个映射的简单类吗? 当然重要的是这种映射是可逆的,否则我必须将映射与其他用户的数据一起保存。

我想避免GUID

GUID索引搜索它们的速度较慢,因为它们不是连续的,因此SQL必须扫描整个索引以匹配特定的GUID,而不仅仅是特定的计算索引页面…

如果我有ID + GUID,那么我总是需要获取原始用户ID来进行任何有意义的数据操作,这又会导致速度下降……

数学可逆整数排列似乎是最快的解决方案……

我会100%使用“向表中添加GUID列”方法。 为每个当前用户生成一个,需要几秒钟,并更新插入过程以为每个新用户生成一个。 这是最好的解决方案。

但是,如果您真的不想采用这种方法,可以使用任何数量的混淆技术。

简单地Base64编码你的号码的字符串表示是一种(坏)方式。

  static public string EncodeTo64(string toEncode) { byte[] toEncodeAsBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode); string returnValue = System.Convert.ToBase64String(toEncodeAsBytes); return returnValue; } static public string DecodeFrom64(string encodedData) { byte[] encodedDataAsBytes = System.Convert.FromBase64String(encodedData); string returnValue = System.Text.ASCIIEncoding.ASCII.GetString(encodedDataAsBytes); return returnValue; } 

糟糕,因为任何拥有半盎司技术知识的人(黑客/剧本倾向于大量拥有)将立即将结果识别为Base64并轻松进行逆向工程。


编辑:此博客文章在带有Rails的URL中混淆ID提供了一个非常可行的示例。 转换为C#可以为您提供以下内容:

 static int Prime = 1580030173; static int PrimeInverse = 59260789; public static int EncodeId(int input) { return (input * Prime) & int.MaxValue; } public static int DecodeId(int input) { return (input * PrimeInverse) & int.MaxValue; } 

输入 – >输出
1234 – > 1989564746
5678 – > 1372124598
5679 – > 804671123

另一位作者的后续post解释了如何通过随机XOR更多地保证这一点,以及如何计算PrimePrimeInverse – 我只是使用原始博客中的预先制作的那些来进行演示。

  1. 使用UUID

  2. 在用户表中创建另一列,例如64位整数,并用随机数填充(每次注册一个新用户 – 生成它并检查它是否唯一)。 数字看起来比UUID好,但需要更多编码。

  3. 使用数学。 ;)您可以生成一对数字XY例如X*Y = 1 (mod M) 。 例如, X=10000000019LY=1255114267LM=2^30 。 然后,您将有两个简单的function:

 long encode(long id) { return (id * X) & M; } long decode(long encodedId) { return (encodedId * Y) & M; } 

它将产生几乎随机的编码ID。 这很容易,但很容易破解。 如果有人愿意破解它,他将能够猜测你的数字并看到编码值。 但是,我并不完全确定它的复杂程度,但是我记得它并不容易破解。

我建议您改用UUID。 当您向数据库添加新用户时,这可以是可索引的并在存储过程中生成。 这意味着要么向数据库表添加新列,要么将包含UUID的新表添加到用户ID作为相关键。

编辑

如果您确实想要避免使用GUID,那么为什么不在访问其个人资料页面时使用用户“用户名”。 毕竟,我想在您输入有效信息并且数据已保存到数据库之前,您不会为用户分配ID。