如何在PHP中创建高效的编码/解码唯一ID

如何在PHP中创建高效的编码/解码唯一ID,php,base64,unique,base32,Php,Base64,Unique,Base32,我试图找到一种方法将数据库ID编码成一个短的URL,例如,1应该变成“Ys47R”。然后我想把它从“Ys47R”解码回1,这样我就可以使用INT值运行数据库搜索。使用数据库ID时,它必须是唯一的。序列不应容易猜测,例如1=“Ys47R”,2=“Ys47S”。它应该是类似于YouTube或bitly的URL的。我已经用md5、base32、base64和`bcpow阅读了数百种不同的源代码,但结果都是空的 看起来很有希望,但一旦我添加了填充和密钥,短ID就变成了SDDDG,2变成了“SDDDH”,

我试图找到一种方法将数据库ID编码成一个短的
URL
,例如,1应该变成“Ys47R”。然后我想把它从“Ys47R”解码回1,这样我就可以使用
INT
值运行数据库搜索。使用数据库
ID
时,它必须是唯一的。序列不应容易猜测,例如1=“Ys47R”,2=“Ys47S”。它应该是类似于YouTube或bitly的
URL的
。我已经用
md5
base32
base64
和`bcpow阅读了数百种不同的源代码,但结果都是空的

看起来很有希望,但一旦我添加了填充和密钥,短ID就变成了SDDDG,2变成了“SDDDH”,3变成了“SDDDI”。这不是很随机的

base32
仅使用a-b 0-9
base64
末尾有==等字符

然后我试了一下:

function getRandomString($db, $length = 7) {

    $validCharacters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    $validCharNumber = strlen($validCharacters);
    $result = "";

    for ($i = 0; $i < $length; $i++) {
        $index = mt_rand(0, $validCharNumber - 1);
        $result .= $validCharacters[$index];
    }
函数getRandomString($db,$length=7){ $validCharacters=“0123456789abcdefghijklmnopqrstuvxyzabcdefghijklmnopqrstuvxyz”; $validCharNumber=strlen($validCharacters); $result=“”; 对于($i=0;$i<$length;$i++){ $index=mt_rand(0,$validCharNumber-1); $result.=$validCharacters[$index]; } 这是可行的,但意味着我每次都必须运行数据库查询,以确保没有冲突,并且数据库中不存在冲突

是否有一种方法可以创建最短的
ID
,该ID至少为4个字符,字符集为
[a-z][a-z][0-9]
可以在每个数字都是唯一的数据库中使用增量唯一的
ID
进行编码和解码。我无法理解使用
base32
base64
的高级技术


或者我是不是研究得太多了,有一种更简单的方法可以做到?最好是执行上面的随机字符串函数,并始终查询数据库以检查唯一性?

您可以使用注释中的函数:

$initial='11111111';
$dic='0123456789ABCDefghijklmnopqrstuvxyzabCDefghijklmnopqrstuvxyz';
var_dump($converted=convBase($initial,'0123456789',$dic));
//串(4)“KCvt”
var_dump(convBase($converted,$dic,'0123456789'));
//字符串(8)“11111111”
函数convBase($numberInput、$fromBaseInput、$toBaseInput)
{
如果($fromBaseInput==$toBaseInput)返回$numberInput;
$fromBase=str_分割($FROMBASEINTPUT,1);
$toBase=str_分割($toBaseInput,1);
$number=str_split($numberInput,1);
$fromLen=strlen($fromBaseInput);
$toLen=strlen($toBaseInput);
$numberLen=strlen($numberInput);
$retval='';
如果($toBaseInput=='0123456789')
{
$retval=0;

对于($i=1;$i来说,如果需要一些对称模糊处理,那么通常就足够了

base_convert($id, 10, 36);
将返回类似
1i0g
的字符串并将其转换回

在基础转换之前和之后,您可以添加:

  • 要获得最小字符串长度,我建议只需将
    70000
    添加到
    $id
    中,然后在接收端再减去它

  • 小乘法
    $id*=3
    将在生成的字母数字id范围中添加一些“孔”,但不会耗尽可用的字符串空间

  • 对于一些随意性的外观,有点咬动:

    $id = ($id & 0xF0F0F0F) << 4    
        | ($id & 0x0F0F0F0) >> 4;
    
    $id=($id&0xf0f)>4;
    
    它用于生成模糊的ID字符串,并返回原始字符串

    非常清楚:这是任何类型的加密。它只是在连续数字之间移动数字跳跃,看起来更随意


您可能仍然不喜欢答案,但在数据库中生成随机ID是真正阻碍ID猜测的唯一方法。

目的是什么?如果编码的数字不可预测,那么是的,您必须随机生成它们,检查它们是否存在,并将它们存储在表actual
ID
键旁边e是将URL转换为bit.ly类型的URL。因此,我可以使用$\u GET参数获取id,将其转换回原始int,这样我就可以对照数据库检查他们所引用的页面,这样我就可以提取详细信息。因此,经过大量阅读,我看到了两个选项,一个是创建和检查db,当创建大量页面时,还可以增加避免冲突,或者像其他人提到的那样,像youtube一样在运行中创建它,bitly和使用base64意味着在创建时不检查数据库,可以在运行中进行,每个数字都是唯一的,最多可达十亿。主题很清楚。但是为什么要转换页面ID?这是伪安全功能吗?这是basica基本上只是模糊处理(对于这种情况,base32只需添加一个基值来增加输出长度,再加上一些位洗牌就足够了)没错,这是假设更多的混淆,加上好看的url。一个例子是,用户将发送报告链接到客户端,因此好看的短url。同时,虽然不是机密和公共知识,但我不希望有人开始在url中键入用户或客户端的id号1,2,3,4,以查看每一个链接其他人一个接一个地工作,等等。你能用base64减去==号做洗牌位并解码回来吗?这是我发现的一个链接,虽然它提到了它,但它没有说他们是如何使用base64来创建id的,但类似的概念是使用$\u get来创建唯一的短URL。我确实看到了这个方法,那个方法让我回到了我关于短id的问题例如1。如果你看一看,如果你输入1,生成的id也是1,即使你输入11,结果也是a,所以我在这里提到的两个问题,id也不像“Ys47R”这也不是不可预测的,一切都是按顺序进行的,所以很容易猜测。@user3882771,如果您真的需要从
Ys47R
开始,只需在编码前添加数字“893269206”,在解码后添加减法。谢谢您的尝试
$id = ($id & 0xF0F0F0F) << 4    
    | ($id & 0x0F0F0F0) >> 4;