我有一个订单表,我想为用户提供一个订单的唯一代码,同时隐藏递增的标识整数主键,因为我不想泄露已发出多少订单。
确保代码唯一的一种简单方法是使用主键来确定代码。
那么如何将一个整数转换为一个友好的,比如说,八个字母数字代码,以便每个代码都是唯一的?
我有一个订单表,我想为用户提供一个订单的唯一代码,同时隐藏递增的标识整数主键,因为我不想泄露已发出多少订单。
确保代码唯一的一种简单方法是使用主键来确定代码。
那么如何将一个整数转换为一个友好的,比如说,八个字母数字代码,以便每个代码都是唯一的?
最简单的方法(如果您想要字母数字代码)是将整数主键转换为 HEX(如下所示)。而且,您可以使用 `PadLeft()' 来确保字符串有 8 个字符。但是,当订单数量增加时,8 个字符就不够了。
var uniqueCode = intPrimaryKey.ToString("X").PadLeft(8, '0');
或者,您可以在将其转换为 HEX 之前创建主键的偏移量,如下所示:
var uniqueCode = (intPrimaryKey + 999).ToString("X").PadLeft(8, '0');
如果你想要一些难以追踪的东西并且你不介意它是 16 个字符,你可以使用这样的东西,其中包括一些随机数并将原始输入的字节位置与它们混合:(编辑制作一个通过与生成的随机数进行异或运算,更难以追踪)。
public static class OrderIdRandomizer
{
private static readonly Random _rnd = new Random();
public static string GenerateFor(int orderId)
{
var rndBytes = new byte[4];
_rnd.NextBytes(rndBytes);
var bytes = new byte[]
{
(byte)rndBytes[0],
(byte)(((byte)(orderId >> 8)) ^ rndBytes[0]),
(byte)(((byte)(orderId >> 24)) ^ rndBytes[1]),
(byte)rndBytes[1],
(byte)(((byte)(orderId >> 16)) ^ rndBytes[2]),
(byte)rndBytes[2],
(byte)(((byte)(orderId)) ^ rndBytes[3]),
(byte)rndBytes[3],
};
return string.Concat(bytes.Select(b => b.ToString("X2")));
}
public static int ReconstructFrom(string generatedId)
{
if (generatedId == null || generatedId.Length != 16)
throw new InvalidDataException("Invalid generated order id");
var bytes = new byte[8];
for (int i = 0; i < 8; i++)
bytes[i] = byte.Parse(generatedId.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber);
return (int)(
((bytes[2] ^ bytes[3]) << 24) |
((bytes[4] ^ bytes[5]) << 16) |
((bytes[1] ^ bytes[0]) << 8) |
((bytes[6] ^ bytes[7])));
}
}
用法:
var obfuscatedId = OrderIdRandomizer.GenerateFor(123456);
Console.WriteLine(obfuscatedId);
Console.WriteLine(OrderIdRandomizer.ReconstructFrom(obfuscatedId));
缺点:如果知道算法,显然很容易被破解。优点:它是完全自定义的,即不是像 MD5 这样的既定算法,如果您不知道正在使用什么算法,可能更容易猜测/破解。
假设正在创建的订单总数不会接近池中标识符的总数,一个相当有效的技术是简单地生成一个随机标识符并查看它是否已被使用;继续生成新的标识符,直到找到以前没有使用过的标识符。
一种快速简便的方法是创建一个 guid 列,其默认值为
left(newid(),8)
此解决方案通常会为您提供每一行的唯一值。但是,如果您有大量订单,这将不是唯一的,您应该只使用 newid() 值来生成 guid。
我会为此使用MD5。MD5 为代表客户订单的一小部分整数提供了足够的“唯一性”。
例如,请参阅此答案。您需要将输入参数从 string 调整为 int (或者只需调用ToString
您的号码并按原样使用代码)。