1

我正在尝试找到一种将数据库 ID 编码为 short 的方法URL,例如 1 应变为“Ys47R”。然后我想将它从“Ys47R”解码回 1,这样我就可以使用该INT值运行数据库搜索。它需要使用数据库是唯一的ID。序列不应轻易猜到,例如 1 = "Ys47R", 2 = "Ys47S"。它应该类似于 YouTube 或 bitly 的URL'smd5我已经使用、和 `bcpow阅读了数百个不同的来源base32base64但结果都是空的。

这篇博文看起来很有希望,但是一旦我添加了填充和密码,短 ID,例如 1 变成了 SDDDG,2 变成了“SDDDH”,3 变成了“SDDDI”。这不是很随机。

base32仅使用 ab 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];
    }

这有效,但意味着我每次都必须运行数据库查询以确保没有冲突并且它在数据库中不存在。

有没有一种方法可以创建ID's至少 4 个字符的短字符集,其中的字符集[a-z][A-Z][0-9]可以编码和解码回来,ID在每个数字都是唯一的数据库中使用增量唯一。我无法理解使用base32or的高级技术base64

或者我是否对此进行了太多研究,并且有更简单的方法可以做到这一点?最好做上面的随机字符串函数并查询数据库以检查唯一性吗?

4

2 回答 2

1

您可以使用评论中的功能:http: //php.net/manual/en/function.base-convert.php#106546

$initial = '11111111';
$dic = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
var_dump($converted = convBase($initial, '0123456789', $dic)); 
// string(4) "KCvt"
var_dump(convBase($converted, $dic, '0123456789')); 
// string(8) "11111111"

function convBase($numberInput, $fromBaseInput, $toBaseInput)
{
    if ($fromBaseInput==$toBaseInput) return $numberInput;
    $fromBase = str_split($fromBaseInput,1);
    $toBase = str_split($toBaseInput,1);
    $number = str_split($numberInput,1);
    $fromLen=strlen($fromBaseInput);
    $toLen=strlen($toBaseInput);
    $numberLen=strlen($numberInput);
    $retval='';
    if ($toBaseInput == '0123456789')
    {
        $retval=0;
        for ($i = 1;$i <= $numberLen; $i++)
            $retval = bcadd($retval, bcmul(array_search($number[$i-1], $fromBase),bcpow($fromLen,$numberLen-$i)));
        return $retval;
    }
    if ($fromBaseInput != '0123456789')
        $base10=convBase($numberInput, $fromBaseInput, '0123456789');
    else
        $base10 = $numberInput;
    if ($base10<strlen($toBaseInput))
        return $toBase[$base10];
    while($base10 != '0')
    {
        $retval = $toBase[bcmod($base10,$toLen)].$retval;
        $base10 = bcdiv($base10,$toLen,0);
    }
    return $retval;
}
于 2014-07-28T02:02:55.510 回答
0

如果你想要一些对称的混淆,那么base_convert()通常就足够了。

base_convert($id, 10, 36);

将返回类似的字符串1i0g并将它们转换回来。

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

  • 要获得最小字符串长度,我建议只添加70000到您的$id. 在接收端再次减去它。

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

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

    $id = ($id & 0xF0F0F0F) << 4    
        | ($id & 0x0F0F0F0) >> 4;
    

    这适用于生成您的混淆 ID 字符串,并取回原始的。

    只是要清楚:这不是任何形式的加密。它只是在连续数字之间移动数字跳跃,看起来稍微随意一些。

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

于 2014-07-28T03:51:13.387 回答