1

我想实现一个类似于Imgur的保存系统,如果用户按下按钮,则返回唯一的 5 个字符值。这是我到目前为止所拥有的:

数据库后端使用从 开始的自动递增 ID 5308416。我使用修改后的 Radix 函数(见下文)将这些数字 ID 转换为字符。我使用反向函数将字符 ID 查找回数字数据库 ID。

function genID (value)
{
    var alphabet = "23456789BCDFGHJKLMNPRSTVWXYZbcdfghjkmnpqrstvwxyz";

    var result = "";
    var length = alphabet.length;

    while (value > 0)
    {
        result = alphabet[value % length] + result;
        value  = Math.floor (value / length);
    }

    return result;
}

问题是这些生成的 ID 是非常可预测的。我的问题是,如何使生成的 ID 看起来是随机的但仍然是唯一的(所以我可以在数据库中将它们作为数字查找)。我正在考虑使用一些加密算法,但不知道从哪里开始。任何帮助或建议将不胜感激(也许还有更好的方法)。

4

2 回答 2

1

您是否必须能够双向使用(即将整数转换为哈希并再次返回)?如果您可以存储散列并以这种方式查找内容,那么创建一个生成难以猜测但完整的散列空间的函数相对容易。您使用素数生成一个序列,该序列仅在所有可能的排列都用尽后才重复。

以下 PHP 示例来自我自己的代码,改编自此站点

function hash($len = 6) {
    $base = 36;
    $gp = array(1,23,809,28837,1038073,37370257 /*,1345328833*/);
    $maxlen = count($gp);
    $len = $len > ($maxlen-1) ? ($maxlen-1) : $len;
    while($len < $maxlen && pow($base,$len) < $this->ID) $len++; 
    if($len >= $maxlen) throw new Exception($this->ID." out of range (max ".pow($base,$maxlen-1).")");
    $ceil = pow($base,$len);
    $prime = $gp[$len];
    $dechash = ($this->ID * $prime) % $ceil;
    $hash = base_convert($dechash, 10, $base);
    return str_pad($hash, $len, "0", STR_PAD_LEFT);
}

在 JavaScript 中实现这一点很容易,但理想情况下你也不需要 - 你的表上有一个插入触发器,它用该算法的结果填充哈希字段(当然适用于 SQL)。

于 2012-08-15T02:06:15.797 回答
0

通过将您的服务器端自动递增数字与当前日期/时间块或随机数相结合,可以生成一个不可预测但唯一的 ID。服务器端自动递增数字保证唯一性,而日期/时间块或随机数消除了可预测性。

对于将服务器端唯一编号作为输入并在客户端添加日期/时间块的字符串形式的唯一 ID,您可以执行以下操作:

function genID(serverNum) {
    return(serverNum + "" + (new Date).getTime());
}

或使用随机数:

function genID(serverNum) {
    return(serverNum + "" + Math.floor(Math.random() * 100000));
}

但是,最好在服务器上添加日期/时间元素,然后将整个唯一 ID 存储在数据库中。

于 2012-08-15T02:50:45.763 回答