【发布时间】:2013-02-03 16:03:24
【问题描述】:
我需要一种有效的方法来获取 random 和 unique 字符串,并且重复的可能性为零(或可忽略不计)。
我需要[0-9A-z] 范围内的字符。
这是我目前所拥有的:
substr(sha1(mt_rand().uniqid()),0,22);
【问题讨论】:
我需要一种有效的方法来获取 random 和 unique 字符串,并且重复的可能性为零(或可忽略不计)。
我需要[0-9A-z] 范围内的字符。
这是我目前所拥有的:
substr(sha1(mt_rand().uniqid()),0,22);
【问题讨论】:
既然我知道这实际上是在谈论 bcrypt 和密码加盐,现在我真的可以将阅读本文的人指向他们应该使用的功能,而不是手动滚动他们自己的加盐系统。
使用password_hash($input, PASSWORD_DEFAULT); 生成适合插入数据库的散列。这将为您取盐。
插入:
$hash = password_hash($_POST["password"], PASSWORD_DEFAULT, ["cost" => 16]);
DB::table("users")->insert(["username" => $user, "password" => $hash]);
// or whatever database method you use to insert data
验证:
$hash = DB::table("users")->fetchByName($username)->select("password");
$input = $_POST["password"];
$verified = password_verify($input, $hash); // true if the password matches
在 PHP 5.5 之前的版本中,使用 https://github.com/ircmaxell/password_compat 作为插件1
当随机生成盐时,碰撞的几率是
1 / [number of possible letters/numbers] ** [length]
对于 22 个字符的字符串来说,这是不可能的低(嗯,不是 不可能,而是 可以忽略不计)
1 / (22 ** 60) = 1 / (3.51043 x 10**80)
看到了吗? 很小。
如果您需要一个真正随机的字符串(注意:这些字符串只是映射到字母的一行数字),那么您就有点不走运了。
您正在寻找的是 CSPRNG(加密安全伪随机数生成器)。不需要唯一性。
正如 @Guarav 在他的回答中指出的那样,您可以使用时间戳作为种子,然后对其进行哈希处理。这称为 UUID(唯一通用标识符,如果它是 128 位时间戳)是可预测的,并且由于多种原因可能会很糟糕:
尽管如此,在足够准确的情况下,您仍然可以将时间戳用作唯一盐。不是 random(除非您将其用作随机种子并将其基本转换为 base10,这仍然是一个坏主意)。如果您可以在纳秒以下计算时间并喜欢将其用作唯一 ID,请考虑这一点。 PHP 无法以足够快的速度处理以提供两个冲突的亚纳秒 ID1(但这并不意味着您不应该验证!)
1:它适用于作曲家!
【讨论】:
这就是我有时会做的事情......
// chars
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-+';
// convert to array
$arr = str_split($chars, 1);
// shuffle the array
shuffle($arr);
// array to chars with 22 chars
echo substr(implode('', $arr), 0, 22);
输出
xd*thKM$B#13^)9!QkD@gU
ixXYL0GEHRf+SNn#gcJIq-
$0LruRlgpjv1XS8xZq)hwY
$G-MKXf@rI3hFwT4l9)j0u
为确保它是唯一的,您可以随时签入您的数据库。万一重复生成KEY。
【讨论】:
$pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; return substr(str_shuffle(str_repeat($pool, 22)), 0, 22);
您可以检查我自己的问题的答案。 How to generate Unique Order Id (just to show touser) with actual Order Id?
您可以使用 TimeStamp 代替任何随机字符串。
关于你的解决方案,有碰撞的可能性,但它的水平很低。
【讨论】:
您不能保证这将始终返回一个唯一值,但它会显着降低风险。使用随机数生成算法时,总是有重复的可能性。
为确保仅生成唯一值,您可以搜索以前生成的值并丢弃重复项。
一些减少公式中重复机会的建议:
sha1。这是一种为任何给定输入返回一个一致输出的方法。它不会影响重复的可能性。sha1(例如,基数为 36 的数字可以使用字符 0-9 和 A-Z,您可以将它们存储在数据库中或您正在执行的任何操作中)随机字符串输出)。但我真的不会在这里选择 36,也许是 256+?substr 将字符串限制为22 个字符,因此您实际上稍微增加了重复的机会。使用我在上一个项目符号中所写的内容将随机数转换为不需要截断的少于 22 个字符的字符串。sha1 函数返回一个 原始 值来消除对 substr 的需求,该值只有 20 个字符。【讨论】:
为什么不直接使用time() 函数。
我需要做类似的事情,一个保持唯一 ID 的解决方案,我最终得到了一个使用 PHP 函数 time() 的解决方案,就像这样 $reference_number = 'BFF-' . time(); 你可以将 BFF 更改为对你的业务逻辑更有意义的东西.这样我就不必担心是否正在生成的新 id 之前被占用,因为时间总是唯一的
希望对你有帮助
【讨论】: