用户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更多地保证这一点,以及如何计算Prime
和PrimeInverse
– 我只是使用原始博客中的预先制作的那些来进行演示。
-
使用UUID
-
在用户表中创建另一列,例如64位整数,并用随机数填充(每次注册一个新用户 – 生成它并检查它是否唯一)。 数字看起来比UUID好,但需要更多编码。
-
使用数学。 ;)您可以生成一对数字
X
,Y
例如X*Y = 1 (mod M)
。 例如,X=10000000019L
,Y=1255114267L
,M=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。