我想实现类似于Imgur的保存系统,如果用户按下按钮,则返回唯一的5个字符值。以下是我到目前为止的情况:
数据库后端使用从5308416
开始的自动递增ID。我使用修改的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看起来随机但仍然是唯一的(所以我可以在数据库中查找它们作为数字)。我在考虑使用一些加密算法,但不知道从哪里开始。任何帮助或建议将不胜感激(也许还有一种更好的方法)。
答案 0 :(得分:1)
你必须能够双向进行(即将整数转换为哈希值并再次返回)吗?如果您可以存储哈希并以这种方式查找内容,那么创建一个产生难以猜测但完整的哈希空间的函数相对容易。您使用素数生成一个序列,只有在所有可能的排列都用完后才会重复。
以下PHP示例是from my own code,改编自this site:
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,疗程)。
答案 1 :(得分:0)
通过将服务器端自动递增数与当前日期/时间块或随机数组合,可以生成不可预测但唯一的ID。服务器端自动递增数字保证唯一性,日期/时间块或随机数消除了可预测性。
对于字符串形式的唯一ID,它将服务器端唯一编号作为输入,并在客户端上添加日期/时间块,您可以这样做:
function genID(serverNum) {
return(serverNum + "" + (new Date).getTime());
}
或使用随机数:
function genID(serverNum) {
return(serverNum + "" + Math.floor(Math.random() * 100000));
}
但是,最好在服务器上添加日期/时间元素,并将整个唯一ID存储在数据库中。