我整天都在阅读有关该主题的文章,但我不确定如何继续。
我有一个MySQL用户表,其主键为UUID_SHORT()值和一个电子邮件字段,这也是唯一的。我需要能够生成一个始终唯一的,不可猜测的ID,以便在激活URL中使用。像这样:
http://example.com/activate.php?id=tKd32f
阅读此问题后:How to code a URL shortener?
我已经实现了一个base58编码方法,我试图使用代表用户的UUID_SHORT()值,由MySQL服务器生成。
<?php
function base58_encode($num, $alphabet)
{
$base_count = strlen($alphabet);
$alphabet = str_split($alphabet);
echo "base_count: " . $base_count . "<br>";
$encoded = '';
while ($num >= $base_count)
{
$div = $num/$base_count;
echo "div: " . $div . "<br>";
$mod = ($num-($base_count*intval($div)));
echo "mod: " . $mod . "<br>";
echo "alphabet[$mod]: " . $alphabet[$mod] . "<br>";
$encoded = $alphabet[$mod] . $encoded;
echo "encoded: " . $encoded . "<br>";
$num = intval($div);
echo "num: " . $num . "<br>";
echo "------------------------------<br>";
}
if ($num) $encoded = $alphabet[$num] . $encoded;
return $encoded;
}
$alphabet = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
echo "WORKS => " . base58_encode(3707787591, $alphabet) . "<br><br>"; // some random number
echo "DOES NOT WORK => " . base58_encode(23298059492392988, $alphabet); // one of the unique IDs in my database
?>
如果我使用10位数字,它可以工作。但是如果我使用较长的UUID_SHORT值,我会得到一个未定义的偏移量错误,因为$ num = intval($ div)在其param太大时返回一个负数。我似乎无法弄清楚原因,但似乎与:http://ca1.php.net/intval
有关我的问题:
这甚至是正确的方法吗?我应该使用UUID_SHORT值来生成激活码还是太可猜测?如果我在MySQL服务器上多次执行SELECT UUID_SHORT(),你可以看到这个值增加1(这让我担心)。
如果这个base58_encode是正确的方法,我该如何解决这个错误?如何获得更短的激活码,与goo.gl的url缩短服务不同。他们是如何做到的呢?我找不到明确的答案。
我应该使用更多的内容吗? How to generate a secure activation string in php? 但是,这会生成一个非常长的ID。在我的情况下并不是真的有必要,它会产生更丑陋的激活URL。
我计划在一段时间后使我的网址过期,但ID必须始终是唯一的(理想情况下,足够短)。我也不需要稍后解码该值,因为我将唯一生成的ID映射到数据库中的用户ID。这里最好的方法是什么?
感谢您的时间。
答案 0 :(得分:1)
这是一个建议:
制作表格的网址
www.example.com/?code=XXXXX-YYYYY-ZZZZZ
其中
XXXXX是数据库中客户的唯一标识符
YYYYY是种子的小数部分,种子的另一部分存储在针对XXXXX的数据库中(YYYYY 不存储)
ZZZZZ是XXXXXX的sha512哈希的随机段,以及存储在数据库中的段的起点和终点的完整种子。
作为数据库中用于身份验证的最后一个字段(即计算标识符的第5个字段),有一个用于使链接过期的时间戳。
示例:强>
请求网址。
调用 uniqid()
并将其分配给XXXXX(即13个字符)
让种子成为另一个uniqid("", true)
的sha512哈希,并选择前5个字符作为YYYYY,将余数分配给数据库。
让ZZZZZ成为hash("sha512", SEED . XXXXX)
的第8-15个字符,在数据库中存储8和15。 (随机选择8和15,ofc。)
将时间存储在数据库中。
通过电子邮件发送结果网址。
<强>讨论:强>
由于XXXXX创建时带有uniqid()和一个很难猜测黑客的点,因此轻微安全,但几乎100%独特。
由于种子未完全存储,但是需要验证ZZZZZ,因此实现了更高的安全性,但由于仅存储了子串,因此与使用较长的身份验证方案相比,可能更容易生成冲突。
5个存储的元素形成了一种关键,可以通过一个不易逆转的多步骤过程来验证用户,因此知道该方法在破解方案时没有给予太多帮助(如果有的话)。 / p>
假设在链接失效之前只允许有限数量的猜测。
这不 100%安全 - 没有什么依赖于点击的简单链接,其中链接包含验证所需的所有内容将永远是完全安全的,但它将使其具有相当大的挑战性黑客在允许的时间内实现黑客攻击(取决于您允许链接有效的时间长度)。
我希望这有帮助!