我需要一种有效的方法来获取随机和唯一字符串,并且重复的可能性为零(或可忽略不计)。
我需要[0-9A-z]
范围内的字符。
这是我到目前为止所做的:
substr(sha1(mt_rand().uniqid()),0,22);
答案 0 :(得分:8)
因为我知道这实际上是在谈论bcrypt和密码salting现在我真的可以只是将人们读到这个应该使用的功能,而不是手动滚动他们自己的盐系统。
使用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位时间戳)是可预测的,并且可能由于多种原因而变坏:
尽管如此,如果准确度足够高,您仍然可以将时间戳用作唯一盐。不是随机(除非你将它用作随机种子并将其转换为base10,这仍然是一个坏主意)。如果您可以在纳秒内计算时间并将其用作唯一ID,那么请考虑这一点。 PHP无法快速处理以提供两个碰撞的亚纳秒ID 1 (但这并不意味着您不应该验证!)
1:它与作曲家合作!
答案 1 :(得分:4)
这是我正在做的事情......
// 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。
答案 2 :(得分:2)
您可以查看我自己问题的答案。 How to generate Unique Order Id (just to show touser) with actual Order Id?
您可以使用 TimeStamp 代替任意随机字符串。
关于你的解决方案,有可能发生碰撞,但其处于非常低的水平。
答案 3 :(得分:1)
您不会保证这将始终返回唯一值,但它会显着降低风险。使用随机数生成算法时,总是存在重复的可能性。
为了保证只生成唯一值,您可以搜索以前生成的值并丢弃重复项。
一些建议可以减少公式中重复的可能性:
sha1
。这是一种为任何给定输入返回一致输出的方法。它不会影响重复的可能性。sha1
,您可以使用字符0-9和AZ,您可以将它们存储在数据库中39;重做随机字符串输出)。但我不会在这里找到36,也许是256 +?substr
将字符串限制为22个字符,因此实际上会增加重复次数的可能性。使用我在上一个项目符号中写的内容将随机数转换为少于22个字符且不需要截断的字符串。substr
函数返回原始值来删除对sha1
的需求,该函数只有20个字符。答案 4 :(得分:-1)
为什么不使用time()
函数。
我需要做类似的事情,一个保持唯一ID的解决方案,我最终得到了一个使用PHP函数time()
的解决方案,就像这样$reference_number = 'BFF-' . time();
你可以将BFF更改为更有意义的东西对你的业务逻辑。这样我就不必担心是否因为时间永远是唯一的,所以正在生成新的id
我希望这会有所帮助