在PHP中生成随机的字母数字字符串

首先,让我说几乎没有事件是真正随机的。 如果我们知道所涉及的每个因素(例如空气摩擦,重力和初始力)的影响,那么即使从理论上讲,经典的抛硬币的结果也可以预测。

同样的情况适用于随机数和字母数字字符串的生成。 我们可以期望的最好的办法是生成似乎不遵循某种模式并且实际上无法被攻击者预测的数字和字符串。

在本教程中,我们将介绍在PHP中生成随机数和字母数字字符串的不同技术。 其中一些将是加密安全的,而另一些则仅用于临时使用,例如分配伪随机文件名或创建URL并建议用户名。

在PHP中生成随机数

在PHP中,可以使用三种不同的函数来生成随机数。 它们都将接受随机数的最小和最大值,并为您输出一个随机数。 这些是rand($min, $max)mt_rand($min, $max)random_int($min, $max)

使用rand() ,您可以生成的整数的最小值和最大值在0getrandmax()返回的值之间。 在PHP 7.1.0之前,此功能比mt_rand()慢大约四倍。 但是,从PHP 7.1.0开始,它已成为mt_rand()的别名。 但是,与mt_rand()不同,您可以将$max的值设置为小于$min而不引起错误。

使用mt_rand() ,可以生成的整数的最小值和最大值介于0mt_getrandmax()返回的值之间。 它依靠Mersenne Twister的实现来生成随机数。 但是请注意,在PHP 7.1.0之前,此函数实现了错误版本的算法来生成数字。 但是,它已在较新版本中修复。

通过消除模块偏差错误,该功能在PHP 7.2.0中变得更好。 这意味着对于某些特定的种子,您的随机数序列现在将比旧版本更好。 但是,某些专用代码实际上可能依赖于这种偏见。 如果是这样,则可以通过调用mt_srand()函数为随机数生成器作为种子并将MT_RAND_PHP用作第二个参数的值来使用较早的种子算法。

mt_rand()函数的周期为2 19937 -1,这基本上意味着,在最佳情况下,在序列开始重复之前,您将获得2 19937 -1个随机数。 您应注意,序列的重复与特定编号的重复不同。 换句话说,您可能会两次获得相同的随机数,但这并不意味着序列本身已经开始重复。 以下序列是一个示例:

187 3276 1267 15 1267 34598 3467 125 17

在上面的序列中,输出两次有1267,但这并不意味着整个序列在此之后开始重复。 不可能很快以随机顺序重复相同的数字,但是有可能!

加密安全随机整数

如果您希望使用密码安全的伪随机数,那么PHP中的random_int()函数是您最好的选择。 它将在提供的$min$max值之间生成随机数,默认为PHP_INT_MINPHP_INT_MAX 。 不幸的是,此功能仅从PHP 7.0起可用。 对于之前的版本,您可以在GitHub上使用此polyfill

随机浮动

除了生成随机整数,您可能还希望生成浮点数。 只需将随机数除以mt_getrandmax()返回的值,就可以轻松完成此操作。 下面的示例将说明如何生成介于0和1之间或任何其他最小与最大限制之间的随机浮点数。

<?php

// Output: 0.69458310943776
echo mt_rand(0, mt_getrandmax())/mt_getrandmax();

function mt_random_float($min, $max) {
    $float_part = mt_rand(0, mt_getrandmax())/mt_getrandmax();
    $integer_part = mt_rand($min, $max - 1);
    return $integer_part + $float_part;
}

// Output: 10.199064863938
echo mt_random_float(10, 11);

// Output: 35.540808309121
echo mt_random_float(15, 50);

?>

在给定限制之间生成随机浮点数时,我们确保随机整数不会超过$max - 1 。 这样,我们可以确保添加浮点数不会超过最大限制。

播种随机数生成器

需要一点解释的一个概念是种子。 简而言之,这些只是可用于在生成任何随机数之前初始化rand()mt_rand()函数的数字。 播种rand()的函数称为srand($seed) ,播种mt_rand()mt_srand($seed, $mode)称为mt_srand($seed, $mode)

重要的是要记住,在调用rand()mt_rand()之前每次提供初始种子值不一定会产生更好的随机数。 实际上,每次使用相同的种子也将为您提供相同的随机数!

<?php

mt_srand(10);
// Output: 1656398468
echo mt_rand();

mt_srand(10);
// Output: 1656398468
echo mt_rand();

mt_srand(10);
// Output: 1656398468
echo mt_rand();

?>

在要生成随机但可重现的序列的情况下,播种随机数很有用。 下面的代码片段在运行两次时会生成相同的随机数序列。

<?php

mt_srand(10);

$count = 0;

while($count < 10) {
    echo mt_rand(0, 100)." ";
    $count++;
}

// Output on First Run:
// 68 58 68 13 3 48 30 37 96 82

// Output on Second Run:
// 68 58 68 13 3 48 30 37 96 82

通过这种方式生成可重现的随机序列可以帮助调试使用随机数据测试的程序-如果您跟踪种子,则可以重现相同的输入以找出问题所在。

在PHP中生成随机字母数字字符串

生成随机字母数字字符串的方法有很多,具体使用哪种取决于您的需求。

生成随机的字符串

如果要从一组固定的字符生成随机的字母数字字符串,可以使用str_shuffle($string)函数。 此函数将为您提供随机混洗的字符串。 从PHP 7.1开始,用于确定输出字符串中字符的随机顺序的算法已更改为Mersenne Twister。

请记住,以这种方式生成的随机字符串不是加密安全的。 但是,对于生成随机文件名或URL之类的常用字符串而言,该字符串仍然非常难以预测。 这里有一些例子:

<?php

$permitted_chars = '0123456789abcdefghijklmnopqrstuvwxyz';
// Output: 54esmdr0qf
echo substr(str_shuffle($permitted_chars), 0, 10);

$permitted_chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
// Output: video-g6swmAP8X5VG4jCi.mp4
echo 'video-'.substr(str_shuffle($permitted_chars), 0, 16).'.mp4';

?>

在两种情况下,您的输出很可能会有所不同。 在第一种情况下,我们只是对允许的字符串进行了混洗,然后采用了它的前10个字符。 在第二种情况下,我们在生成的字符串的开头添加了“视频”,并在其结尾添加了“ .mp4”。

这种生成随机字母数字字符串的方法非常简单,但是存在两个问题。 例如,您永远不会在随机字符串中两次获得相同的字符。 同样,随机输出字符串的长度只能与输入字符串一样长。

生成随机字符串

如果我上面列出的问题破坏了交易,那么您可能希望查看其他一些实现。 以下代码将解决这两个问题。

<?php

$permitted_chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

function generate_string($input, $strength = 16) {
    $input_length = strlen($input);
    $random_string = '';
    for($i = 0; $i < $strength; $i++) {
        $random_character = $input[mt_rand(0, $input_length - 1)];
        $random_string .= $random_character;
    }

    return $random_string;
}

// Output: iNCHNGzByPjhApvn7XBD
echo generate_string($permitted_chars, 20);

// Output: 70Fmr9mOlGID7OhtTbyj
echo generate_string($permitted_chars, 20);

// Output: Jp8iVNhZXhUdSlPi1sMNF7hOfmEWYl2UIMO9YqA4faJmS52iXdtlA3YyCfSlAbLYzjr0mzCWWQ7M8AgqDn2aumHoamsUtjZNhBfU
echo generate_string($permitted_chars, 100);

?>

您可以对其进行修改,以在生成的随机字符串中添加特定的后缀和前缀。 使用PHP 7的人可以使用加密安全的函数random_int()而不是mt_rand()来进一步改善字符串生成。

生成随机的十六进制字符串

如果要在PHP中生成随机的十六进制字符串,还可以使用md5($string, $raw_output)sha1($string, $raw_output)函数。 它们都将生成给定输入字符串的哈希。

只要输入是唯一的,您就将不断获得唯一的哈希。 这可以通过使用类似time()的函数的输出作为输入来实现。 默认情况下, md5()将返回32个字符的十六进制字符串,而sha1()将返回40个字符的十六进制字符串。 可以使用substr()函数将它们修剪为特定的长度。

这是这些函数返回的输出的示例:

<?php

// Output: 36e5e490f14b031e
echo substr(md5(time()), 0, 16);

// Output: aa88ef597c77a5b3
echo substr(sha1(time()), 0, 16);

// Output: 447c13ce896b820f353bec47248675b3
echo md5(time());

// Output: 6c2cef9fe21832a232da7386e4775654b77c7797
echo sha1(time());

?>

如您所见,在PHP中生成长达40个字符的随机且唯一的十六进制字符串非常容易。

生成加密安全的随机字符串

到目前为止,我们讨论的生成随机字母数字字符串的三个函数在密码上都不安全。 幸运的是,PHP还具有一个称为random_bytes($length)的函数,用于生成加密安全的伪随机字节。 $length参数确定输出字符串应多长。

一旦有了随机字节的输出,就可以使用bin2hex()函数将其转换为十六进制值。 这将使字符串的长度加倍。

<?php

// Output: b7b33efa07915b60ad55
echo bin2hex(random_bytes(10));

// Output: a2e6cb1f25616324c8a11a2cceb0b47c590949ea
echo bin2hex(random_bytes(20));

// Output: 25af3b86e11884ef5e8ef70a0ad06cba81b89ed6af3781a0
echo bin2hex(random_bytes(24));

?>

可以用来生成加密安全的随机字节的另一个函数是openssl_random_pseudo_bytes($length, &$crypto_strong) 。 第二个参数的值可用于确定是否将使用密码安全算法生成输出字符串。

最后的想法

在本教程中,我们研究了PHP中随机数和字母数字字符串的生成。 生成随机数在各种情况下都非常有用,例如在游戏中,您必须生成敌方玩家或随机为用户提供有关字母的线索,以便他们可以组成一个完整的单词。

就像随机数一样,在许多情况下,随机字母数字字符串的生成也非常有用。 借助str_shuffle() ,您可以选择随机字符串中出现的字符集。 使用sha1()md5() ,您可以轻松生成随机的十六进制序列,而使用random_bytes()可以生成加密安全的字符串。 这将使您生成难以猜测的有意义但随机的文件名和用户名。

希望您喜欢本教程。 如果您有任何疑问,请随时在评论中提问。


翻译自: https://code.tutsplus.com/tutorials/generate-random-alphanumeric-strings-in-php--cms-32132

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值