6

我正在尝试创建一个简短的 5 或 6 个字符的邀请码,该邀请码将在我的网站上创建“组”时生成。组信息存储在组表中。希望加入群组的用户必须有一个邀请码——他们不需要知道其他任何信息。

显然,我需要邀请码是唯一的,并且我希望在没有双重检查的情况下生成唯一的字符串,但是找出代码很困难。我一直在阅读数十个 SO 问题和答案。这就是我想出的:

当将组信息(例如名称)插入组表时,该行自然会被赋予一个唯一的、自动递增的 id。

1)抓住那个ID

2) 将其添加到 1234

3) 将团队名称从 base36 转换为 base10 后,只需将值放在一起即可。“纽约洋基队”是 base10(3994055806027582482648)[1263399405580602758248264820130221060827])

4) 转换为基数 36

5)将代码插入数据库

这保证对每个组都是独一无二的,对吧?碰撞几率为零?我这样说是因为它根本不是随机的。我从一些独特的东西开始,并保持它的独特性,从不引入随机数据。

我有几个问题,因为组名是可重复的,我如何在创建/插入时获取行 ID?这行不通,但这是我所在的位置:

$query = "SELECT id FROM groups WHERE gname = :gname";
...
$uid = $result + '1234';
$hex = md5(":gname NOW()" . uniqid("$uid", true));
base_convert($hex, 10, 36);
intval($str, 36);

$query = "INSERT...";

独特、简短但不可预测,没有所有正确的部分,用户无法使用。

4

3 回答 3

2

这里描述了如何获取最后插入的 auto_increment 值

获得 ID 后,您需要使用带有密钥的对称密钥加密,例如 AES。它保证是唯一的(因为它可以转换回原始明文 - 这称为解密)。

您可以调整块大小以获得所需的长度(以位为单位)。使用 base64,长度将是 4 的倍数(因为 8 位字符被编码为三元组,导致 base64 中的 4 个字符块)。

于 2013-02-21T13:01:43.980 回答
2
$query = "INSERT INTO groups (gname, gadmin) VALUES (:gname, :gadmin)";
    $query_params = array( ':gname' => $trimmed['gname']
                           ':gadmin' => $userid );

    try {
        $stmt = $db->prepare($query);
        $result = $stmt->execute($query_params);
        $gid = $db->lastInsertId();
    }
    catch(PDOException $ex) {
        die("Failed to run query: " . $ex->getMessage());
    }

    // Use this library: https://github.com/ivanakimov/hashids.php
    $hashids = new Hashids\Hashids('this is my constant salt', 5,
                'abcdefghijklmnpqrstuvwxyz0123456789');

    $hash = $hashids->encrypt($gid);

    $query = "UPDATE groups SET invite = '$hash' WHERE id = '$gid'";
    ...

有问题的图书馆负责处理繁重的工作。它本身实际上并没有散列。它加密输入;因为我的行 ID 是唯一的,所以加密的结果也是如此。我不需要解密“哈希”,但该选项存在。我不能严格定义长度,但我可以设置一个最小值并有增长的空间。此外,如您所见,它还允许我定义一个“字母表”。

于 2013-02-21T13:24:15.003 回答
0

为什么不连接创建组的人的 IP 地址或用户 ID,以及包括毫秒在内的时间,然后是 MD5 或 SHA-256 以生成您发布的字符串?这肯定是不可预测和不重复的。

于 2013-02-21T12:46:21.277 回答