我希望之前有人问过这个问题,但我们在这里找不到合适的答案,也没有时间提出我自己的解决方案......
如果我们有一个带有int identity
主键的用户表,那么我们的用户在网站上注册时会有连续的ID。
我们在网站网址上有用户公开个人资料页面:
www.somesite.com/user/1234
其中1234是实际用户ID。没有什么容易看到用户的ID 本身,但它确实让任何人都能够检查我的网站上注册了多少用户...手动增加数量最终让我无效的个人资料。
这是我将可逆ID映射到具有固定长度的看似随机数的主要原因:
www.somesite.com/user/6123978458176573
你能指点我做一个这个映射的简单类吗?当然,这种映射只是可逆的,这一点很重要,否则我必须将映射与其他用户的数据一起保存。
GUID索引搜索它们的速度较慢,因为它们不是连续的,因此SQL必须扫描整个索引以匹配特定的GUID而不是特定的计算索引页...
如果我有ID + GUID,那么我总是需要获取原始用户ID来进行任何有意义的数据操作,这又会导致速度下降......
数学可逆整数排列似乎是最快的解决方案......
答案 0 :(得分:15)
我会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并轻松进行逆向工程。
修改:此博客帖子Obfuscating IDs in URLs with Rails提供了相当可行的示例。转换为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
This follow up post by another author解释了如何使用随机XOR更多地保护这一点,以及如何计算Prime
和PrimeInverse
- 我刚刚使用了预先制作的原创博客的演示。
答案 1 :(得分:1)
使用UUID
在用户表格中创建另一列,例如64位整数,并用随机数填充(每次新用户注册 - 生成它并检查它是唯一的)。数字看起来比UUID好,但需要更多编码。
使用数学。 ;)您可以生成一对数字X
,Y
,例如X*Y = 1 (mod M)
。例如。 X=10000000019L
,Y=1255114267L
和M=2^30
。然后,您将有两个简单的功能:
long encode(long id)
{ return (id * X) & M; }
long decode(long encodedId)
{ return (encodedId * Y) & M; }
它将产生几乎随机的编码ID。这很简单,但很容易破解。如果有人愿意破解它,他将能够猜测你的数字并看到编码值。但是,我并不完全确定它的复杂程度,但是我记得它并不容易入侵。
答案 2 :(得分:0)
我建议你改用UUID。当您将新用户添加到数据库时,这可以是可索引的并在存储过程中生成。这意味着要么向数据库表添加新列,要么添加包含UUID但用户ID为相关键的新表。
修改强>
如果你真的想避免使用GUID,那么为什么不在访问他们的个人资料页面时使用用户“用户名”。毕竟,我想在你输入有效信息并且数据已保存到数据库之前,你不会为用户分配ID。