如何在 php 中正确创建唯一标记?

How to create unique tokens correctly in php?

我是 php 的新手,我正在自学,通常我创建我的标记并将它们插入 table 中,如下所示:

private function create_token($reference, $bytes, $slice)
 {
   $key = substr(preg_replace('/\W/', "", base64_encode(bin2hex(random_bytes($bytes)))), 0, $slice);
   return $reference . $key;
 }

function create_token('token_B8', 34, 22); //token_B8eEr32EEddDsfSDGRGgHHhg

这可能是创建令牌的正确方法,但我怀疑这是否真的是正确的方法,我在想,显然在相同的 table 中有 2 个令牌和 1到 1000000000 正确吗?或者有没有办法创建一个令牌,上面写着: Under no circumstances create an equal token 无需创建函数来检查 table 中的令牌是否已经存在。

我相信我应该做的是创建一个令牌,我创建它的方式是创建一个函数来检查这个令牌是否已经存在于 table,如果存在,它会生成另一个令牌,如果不是,则将其插入 table。这似乎是一种正确的方法,但由于我是新手,我不知道是否有更合适的方法,有人可以让我摆脱这种怀疑吗?谢谢

random_bytes() 生成的字符串具有最大的随机性,从字面上看,您之后对它所做的一切都会减少字符串中的随机性,从而减少它可能的值的数量。

  1. random_bytes()每字节8位随机。
  2. bin2hex() 将输入的每个字节扩展为两个字节。 [x0.5]
  3. base64_encode() 在 4 个输出字节上扩展 3 个输入字节。 [x0.75]
  4. preg_replace('/\W/', "", $input) 有效地从 base64 编码更改为 base62,再次稍微减少 space。 [X??? < 1]

所以大家都说你生成的 22 字节令牌代表 22 * 8 * 0.5 * 0.75 * ??? <= 66 位随机数据​​。所以 <= 73,786,976,294,838,206,464 种可能性。

男孩你好,看起来确实很多,对吧?好吧,不是真的。由于 Birthday Paradox 碰撞的可能性可能会进入导致问题的范围,而您距离填充范围仍有几个数量级的距离。

我想如果我们删除那个毫无意义的 bin2hex() 我们可以挤出另外 66 位总共 132 位?但这 真的 还能给我们带来多少?

5,444,517,870,735,015,415,413,993,718,908,291,383,296

很多。 。我什至不关心那个 preg_replace() 了。

为了完整起见,只 random_bytes(22) 怎么样? 176 位?

95,780,971,304,118,053,647,396,689,196,894,323,976,171,195,136,475,136

我猜要点是:

  1. 不要仅仅因为输出 看起来 乱码就将数据 编码 与“随机化”混淆。 [注意:哈希函数也是如此]
  2. 如果您不知道他们实际在做什么,请不要随意应用functions/encodings。

在代码中:

$input = 'abc';

// all of these outputs contain the SAME amount of entropy, some of them are just longer representations
var_dump(
    $input,
    bin2hex($input),
    base64_encode($input),
    base64_encode(bin2hex($input)),
    bin2hex(base64_encode($input))
);

输出:

string(3) "abc"
string(6) "616263"
string(4) "YWJj"
string(8) "NjE2MjYz"
string(8) "59574a6a"

无论如何,如果随机 ID space 足够大,则更务实的做法是对值设置 UNIQUE 约束,并在尝试插入重复值时让进程失败。您可以放入一些重试逻辑,但很可能它永远不会 运行 除非有人专门利用漏洞 使 您自己通过重试生成重复项和 DoS。 [是的,这是一件事]