我想开发类似于jsfiddle的东西,用户可以在其中输入一些数据,然后“保存”它并获得一个加载该数据的独特随机查找URL。
我不想让保存顺序,因为我不希望任何人抓住我的所有条目,因为有些可能是私人的。但是在服务器上我想按顺序保存它。
在(62 * 62 * 62 * 62 === 14776336)
条目之前,是否存在将数字转换为具有4个字符且没有任何冲突的哈希的函数或技术?
例如,服务器上的第一个条目将在服务器上命名为1
,而iUew3
将命名为用户,服务器上的下一个条目将为2
,但{{1} }给用户......
ueGR
时,服务器需要知道服务器文件ueGR
答案 0 :(得分:8)
可以这样做,但我建议使用64个字符,因为这会使它变得容易多了。 4个6位字符= 24位。
使用以下组合:
强烈建议使用LFSR,因为它会进行良好的加扰。其余的是可选的。所有这些操作都是可逆的,并保证每个输出都是唯一。
当您计算“混洗”数字时,只需将其打包成二进制字符串并使用base64_encode
对其进行编码。
对于解码,只需执行这些操作的反转。
样本(2 ^ 24长的独特序列):
function lfsr($x) {
return ($x >> 1) ^ (($x&1) ? 0xe10000 : 0);
}
function to_4($x) {
for($i=0;$i<24;$i++)
$x = lfsr($x);
$str = pack("CCC", $x >> 16, ($x >> 8) & 0xff, $x & 0xff);
return base64_encode($str);
}
function rev_lfsr($x) {
$bit = $x & 0x800000;
$x = $x ^ ($bit ? 0xe10000 : 0);
return ($x << 1) + ($bit ? 1 : 0);
}
function from_4($str) {
$str = base64_decode($str);
$x = unpack("C*", $str);
$x = $x[1]*65536 + $x[2] * 256 + $x[3];
for($i=0;$i<24;$i++)
$x = rev_lfsr($x);
return $x;
}
for($i=0; $i<256; $i++) {
$enc = to_4($i);
echo $enc . " " . from_4($enc) . "\n";
}
输出:
AAAA 0
kgQB 1
5ggD 2
dAwC 3
DhAH 4
nBQG 5
6BgE 6
ehwF 7
HCAO 8
jiQP 9
+igN 10
aCwM 11
EjAJ 12
gDQI 13
9DgK 14
ZjwL 15
OEAc 16
qkQd 17
3kgf 18
TEwe 19
NlAb 20
pFQa 21
0FgY 22
...
注意:对于使用+
和/
替换-
和_
的网址。
注意:虽然这有效,但对于像你这样的简单场景,创建随机文件名可能更容易,直到它不存在。没有人关心参赛作品的数量。
答案 1 :(得分:1)
以下是我实施它的方式。这是save.php文件(有人可以告诉我它是否有任何设计缺陷):
<?php
$index = file_get_contents('saves/data/placeholder');
$index++;
file_put_contents('saves/data/placeholder', $index);
$string = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
do {
$hash = $string[rand(0, 61)] . $string[rand(0, 61)] . $string[rand(0, 61)] . $string[rand(0, 61)];
} while (file_exists('saves/' . $hash));
file_put_contents('saves/' . $hash, $index);
file_put_contents('saves/data/' . $index, $_REQUEST['data']);
echo $hash;
?>
这是load.php:
<?php
if (!file_exists('saves/' . $_REQUEST['file'])) {
file_put_contents('saves/data/log', 'requested saves/' . $_REQUEST['file'] . "\n", FILE_APPEND);
die();
}
$file_pointer = file_get_contents('saves/' . $_REQUEST['file']);
if (!file_exists('saves/data/' . $file_pointer)) {
file_put_contents('saves/data/log', 'requested saves/data/' . $file_pointer . 'from ' . $_REQUEST['file'] . "\n", FILE_APPEND);
die();
}
echo file_get_contents('saves/data/' . $file_pointer);
?>
希望这有助于其他人。
答案 2 :(得分:0)
在我看来,如果你还在服务器上保留save time of entry
,你可以生成一个哈希函数。 hash = func(id, time)
,但只有hash = func(id)
才能轻松解决
答案 3 :(得分:0)
这是一组奇怪的约束。我经常使用MD5校验和从数据生成唯一的URL。如果用户还没有数据,则无法猜出网址。
我确实理解不想使用数据库 - 如果您以前从未使用过数据库,那么学习曲线可能会有点陡峭。
我不明白“在服务器上按顺序存储事物”的限制。如果您需要知道创建哈希的顺序,我只需将该信息放在一个单独的文件中。您可能必须执行文件锁定或其他类型的黑客攻击,以确保您可以逐步将哈希值附加到该文件。
如果您想要短网址,您可以使用MD5校验和的前缀,也可以使用CRC-32和base64对其进行编码。两者都会为您提供具有相当好概率的唯一网址。
答案 4 :(得分:0)
这是一个可逆的lib,与bcmath一起工作 http://blog.kevburnsjr.com/php-unique-hash
答案 5 :(得分:-1)
这实际上不可逆转。唯一的方法(url shorteners和jsfiddle使用的方法)是将生成的哈希(实际上它是摘要)存储在某种表格/数据结构中,并在检索时查找。
为什么会这样?
传递,例如128个数据字符→4个可见字符摘要,您会丢失大量数据 你不能将剩下的数据存储在这4个字节之间的神奇裂缝中,没有。