在我们的数据库中,每个Person都有一个ID,这是由数据库生成的自增整数。现在,我们想要生成一个更用户友好的字母数字ID,可以公开展示,就像护照号码一样。我们显然不想向用户公开DB ID。对于这个问题,我将称我们需要生成的为UID。
注意:UID并不意味着要替换掉DB ID。您可以把UID看作是DB ID的漂亮版本,我们可以向用户提供它。
我在想,这个UID是否可以作为DB ID的函数。也就是说,我们应该能够为给定的DB ID重新生成相同的UID。
显然,该函数将除了DB ID之外还需要一个“盐”或密钥。
UID不应该是顺序的。也就是说,两个相邻的DB ID应该生成外观不同的UID。
虽然没有必要使UID不可逆。也就是说,如果有人研究了UID几天,并能够进行逆向工程并找到DB ID,那么这是可以接受的。我不认为这会对我们造成任何伤害。
UID应只包含A-Z(仅大写)和0-9。不能包含其他字符,这些字符可能与其他字母或数字混淆,如0和O,l和1等。我想Crockford的Base32编码可以解决这个问题。
UID应具有固定长度(10个字符),而与DB ID的大小无关。我们可以用一些常量字符串填充UID,以使其达到所需的固定长度。DB ID可以增长到任何大小。因此,该算法不应具有任何此类输入限制。
我认为解决这个问题的方法是:
步骤1:哈希。
我了解以下哈希函数:
SHA-1
MD5
Jenkin's
哈希返回一个长字符串。我在这里读到了有关称为XOR折叠的东西,可以将字符串缩短到较短的长度。但是我找不到太多关于它的信息。
步骤2:编码。
我了解以下编码方法:
Crockford Base 32编码
Z-Base32
Base36
我猜测编码的输出将是我要寻找的UID字符串。
步骤3:处理碰撞。
注意:UID并不意味着要替换掉DB ID。您可以把UID看作是DB ID的漂亮版本,我们可以向用户提供它。
我在想,这个UID是否可以作为DB ID的函数。也就是说,我们应该能够为给定的DB ID重新生成相同的UID。
显然,该函数将除了DB ID之外还需要一个“盐”或密钥。
UID不应该是顺序的。也就是说,两个相邻的DB ID应该生成外观不同的UID。
虽然没有必要使UID不可逆。也就是说,如果有人研究了UID几天,并能够进行逆向工程并找到DB ID,那么这是可以接受的。我不认为这会对我们造成任何伤害。
UID应只包含A-Z(仅大写)和0-9。不能包含其他字符,这些字符可能与其他字母或数字混淆,如0和O,l和1等。我想Crockford的Base32编码可以解决这个问题。
UID应具有固定长度(10个字符),而与DB ID的大小无关。我们可以用一些常量字符串填充UID,以使其达到所需的固定长度。DB ID可以增长到任何大小。因此,该算法不应具有任何此类输入限制。
我认为解决这个问题的方法是:
步骤1:哈希。
我了解以下哈希函数:
SHA-1
MD5
Jenkin's
哈希返回一个长字符串。我在这里读到了有关称为XOR折叠的东西,可以将字符串缩短到较短的长度。但是我找不到太多关于它的信息。
步骤2:编码。
我了解以下编码方法:
Crockford Base 32编码
Z-Base32
Base36
我猜测编码的输出将是我要寻找的UID字符串。
步骤3:处理碰撞。
- 为了避免冲突,我想知道在UID生成时能否生成一个随机密钥并在该函数中使用此随机密钥。
- 我可以将此随机密钥存储在一列中,以便我们知道用于生成特定UID的密钥。
- 在将新生成的UID插入表之前,我将检查唯一性,如果检查失败,我可以生成一个新的随机密钥并使用它来生成新的UID。对于特定的DB ID,可以重复此步骤直到找到唯一的UID。
我希望得到一些专家意见,了解我是否走在正确的轨道上,以及如何实际实现这一点。
我将在Ruby On Rails应用程序中实现这个,所以请考虑这一点在你的建议中。
谢谢。
更新
评论和答案让我重新考虑并质疑我所要求的其中一个需求:我们需要在分配一次后重新生成用户的UID。我想我只是想保险起见,在我们丢失用户的UID时,如果它是用户现有属性的功能,我们将能够重新获得它。但是我们可以通过备份解决这个问题,我想。
因此,如果我删除该要求,则UID基本上成为完全随机的10个字符的字母数字字符串。我正在添加一个包含我提出的实施计划的答案。如果其他人提出更好的计划,我将把它标记为答案。