PHP随机字符串生成器

Cap*_*ing 772 php string random

我正在尝试在PHP中创建一个随机字符串,我绝对没有输出:

<?php
    function RandomString()
    {
        $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $randstring = '';
        for ($i = 0; $i < 10; $i++) {
            $randstring = $characters[rand(0, strlen($characters))];
        }
        return $randstring;
    }

    RandomString();
    echo $randstring;
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

Ste*_*ins 1337

要具体回答这个问题,有两个问题:

  1. $randstring 当你回应它时,它不在范围内.
  2. 字符在循环中没有连接在一起.

这是一个带有更正的代码片段:

function generateRandomString($length = 10) {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $charactersLength = strlen($characters);
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, $charactersLength - 1)];
    }
    return $randomString;
}
Run Code Online (Sandbox Code Playgroud)

使用以下调用输出随机字符串:

// Echo the random string.
// Optionally, you can give it a desired string length.
echo generateRandomString();
Run Code Online (Sandbox Code Playgroud)

请注意,这会生成可预测的随机字符串.如果要创建安全令牌,请参阅此答案.

  • 所有这些工作,为什么不只是像`substr(str_shuffle(MD5(microtime())),0,10);`? (188认同)
  • @FranciscoPresencia,在循环的比较条件中调用方法时,最好"浪费"一个额外的变量. (33认同)
  • @FranciscoPresencia你有什么想法是多么可怜的低效率?您每次迭代检查两次字符串的长度!在进入循环之前,循环内的strlen应该缓存在变量中. (5认同)
  • 感谢您的代码,但请将`rand()`更改为`mt_rand()`.我使用了你的方法,经历了与名字碰撞的*吨*. (4认同)
  • 这不是一个好的解决方案.这个生成的字符串是可预测的.:( (4认同)
  • 为什么要浪费那个额外的变量,`$ i`?只做`for($ randomString =''; strlen($ STR)<50;)$ randomString.= $ characters [rand(0,strlen($ characters) - 1)];`而不是你的循环,或简化, `for($ STR =''; strlen($ STR)<50;)$ STR.= $ CHR [rand(0,strlen($ CHR) - 1)];` (2认同)
  • @MatthewT.Baker 你不想在随机字符串中出现重复项吗?如果没有字符可以重复,则(显着!)减少生成字符串中的熵。 (2认同)
  • @RonLugge,我想你误会了,我指的是@ SpYk3HH的"MD5(microtime())"评论. (2认同)
  • @SpYk3HH 不会有大写字母。 (2认同)
  • @PavelBariev 我想,如果你必须有一些大写,你可以像这样改变它: implode('', array_map(function($i) { return rand(1, 10)%2 == 0 ? strtoupper($i) : $i; }, str_split(substr(str_shuffle(MD5(microtime())), 0, 10)))); [博客](http://spyk3lc.blogspot.com/2014/06/i-know-its-been-quite-while-and-i-need.html) (2认同)
  • 对于长度大于 32 个字符的伪随机字符串:`substr(str_shuffle(str_repeat(MD5(microtime()), ceil($len/32))), 0, $len)` (2认同)

A. *_*rov 364

注意:str_shuffle()内部使用rand(),不适合加密目的(例如生成随机密码).你想要一个安全的随机数发生器.它也不允许重复字符.

还有一种方法.

UPDATED (现在生成任意长度的字符串):

function generateRandomString($length = 10) {
    return substr(str_shuffle(str_repeat($x='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($length/strlen($x)) )),1,$length);
}

echo  generateRandomString();  // OR: generateRandomString(24)
Run Code Online (Sandbox Code Playgroud)

而已.:)

  • +1为最短的答案:).但并非每个用例的最佳答案.此代码将输出字符串,其中每个字符不会出现多次(因此对于暴力攻击会使其变弱)并且不会输出超过62个字符的任何内容. (64认同)
  • 它可能很弱,但它快速而简单.根据使用情况,这很好 - 我使用它是因为我不需要安全或力量; 只是一个快速洗牌.我正在写一个单元测试,这给了我一个适当的随机输入来测试. (22认同)
  • @FranciscoPresencia它不安全的原因是因为它从不使用相同的字符两次.这使它成为一个_terrible_密码生成器.请大家停止投票,这绝对不安全,绝对不能使用.随着密码变长,您必须在蛮力中测试的字符数会变短,因为您不需要测试以前使用的任何字符. (22认同)
  • 不要这样做,它是非常弱的.你制作随机字符串的时间越长,它就越弱. (17认同)
  • @FranciscoPresencia:我支持你关于避免将其用于随机密码的评论.但是,我不同意这个答案不应该加一.我有这个选项的加号,因为它是一个有效的单行解决方案,用于生成随机字符串(这个问题的原始主题). (8认同)

Sco*_*ski 310

这个问题有很多答案,但没有一个利用密码安全伪随机数发生器(CSPRNG).

简单,安全和正确的答案是使用RandomLib并且不要重新发明轮子.

对于那些坚持发明自己的解决方案的人,PHP 7.0.0将提供random_int()此目的; 如果你仍然使用PHP 5.x,我们编写了一个PHP 5 polyfill,random_int()因此你甚至可以在升级到PHP 7之前使用新的API.

在PHP中安全地生成随机整数并非易事.在生产中部署本地算法之前,应始终与驻留的StackExchange加密专家核实.

使用安全的整数生成器,使用CSPRNG生成随机字符串就是在公园散步.

创建安全的随机字符串

/**
 * Generate a random string, using a cryptographically secure 
 * pseudorandom number generator (random_int)
 *
 * This function uses type hints now (PHP 7+ only), but it was originally
 * written for PHP 5 as well.
 * 
 * For PHP 7, random_int is a PHP core function
 * For PHP 5.x, depends on https://github.com/paragonie/random_compat
 * 
 * @param int $length      How many characters do we want?
 * @param string $keyspace A string of all possible characters
 *                         to select from
 * @return string
 */
function random_str(
    int $length = 64,
    string $keyspace = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
): string {
    if ($length < 1) {
        throw new \RangeException("Length must be a positive integer");
    }
    $pieces = [];
    $max = mb_strlen($keyspace, '8bit') - 1;
    for ($i = 0; $i < $length; ++$i) {
        $pieces []= $keyspace[random_int(0, $max)];
    }
    return implode('', $pieces);
}
Run Code Online (Sandbox Code Playgroud)

用法:

$a = random_str(32);
$b = random_str(8, 'abcdefghijklmnopqrstuvwxyz');
$c = random_str();
Run Code Online (Sandbox Code Playgroud)

演示:https://3v4l.org/b4PST(忽略PHP 5失败;它需要random_compat)

  • 使用`random_int()`而不是`rand()`或`mt_rand()`为开发人员增加了复杂性.同时,它为他们提供了更大的安全性.前来StackOverflow寻找快速解决方案的人可能不知道他们正在构建的东西是否需要安全.如果我们给他们提供默认的安全答案,他们就会创建一个更安全的互联网,即使从他们的角度来看,这完全是偶然的.为什么你反对这个目标对我来说是一个谜. (41认同)
  • "为了更安全",你的意思是什么?我们已经在使用安全的随机数生成器. (13认同)
  • @JGEstiot创建安全的随机字符串需要加密安全随机性.搜索"如何在PHP中生成随机字符串"的人可以通过安全答案而不是不安全的答案来获得更好的服务. (5认同)
  • 在函数的开头添加`$ keyspace = str_shuffle($ keyspace);`以获得更高的安全性 (3认同)
  • @ Scott Arciszewski 您不需要在每次创建随机字符串时都创建加密随机字符串。问题是关于创建随机字符串,这与安全性无关。您假设该字符串将在安全敏感的上下文中使用,并且您添加了一层复杂性以阻止问题的核心。 (2认同)
  • 我真的很喜欢你的回答,但我质疑自己。为什么在最后使用 implode() 而不是只用 .= 附加新字符而不是将它们添加到数组中?对性能有很大影响吗? (2认同)

Rud*_*die 142

创建一个20 char长的hexdec字符串:

$string = bin2hex(openssl_random_pseudo_bytes(10)); // 20 chars
Run Code Online (Sandbox Code Playgroud)

在PHP 7中(random_bytes()):

$string = base64_encode(random_bytes(10)); // ~14 characters, includes /=+
// or
$string = substr(str_replace(['+', '/', '='], '', base64_encode(random_bytes(32))), 0, 32); // 32 characters, without /=+
// or
$string = bin2hex(random_bytes(10)); // 20 characters, only 0-9a-f
Run Code Online (Sandbox Code Playgroud)

  • 请注意,`openssl_random_pseudo_bytes()` 直到 php 5.6 才使用加密强算法。相关错误:https://bugs.php.net/bug.php?id=70014 (2认同)

Hum*_*rey 87

@tasmaniski:你的回答对我有用.我有同样的问题,我建议那些一直在寻找相同答案的人.这是来自@tasmaniski:

<?php 
    $random = substr(md5(mt_rand()), 0, 7);
    echo $random;
?>
Run Code Online (Sandbox Code Playgroud)

  • 如果你的字符串只基于一个随机整数,为什么不使用随机整数呢?他们的干草堆没有通过散列它来深入了解......并且通过切割你的散列实际上会破坏你必须开始的小熵. (6认同)
  • 请记住`md5`将导致30个字符的限制并始终为小写字符. (4认同)
  • 此外,rand()不应用于加密.如果您要生成密码学上合理的字符串,请使用[openssl_random_pseudo_bytes](http://php.net/manual/en/function.openssl-random-pseudo-bytes.php). (3认同)
  • 嗯..我敢打赌,OP不是在谈论"安全的随机字符串".对于**正确的**用例,这种解决方案紧凑,易于记忆.并且,如果您需要处理可能的冲突,为什么不在随机字符串前加/附加时间戳?:) (2认同)

rjm*_*nro 43

根据您的应用程序(我想生成密码),您可以使用

$string = base64_encode(openssl_random_pseudo_bytes(30));
Run Code Online (Sandbox Code Playgroud)

作为base64,它们可能包含=或者包含-所请求的字符.您可以生成一个更长的字符串,然后过滤并修剪它以删除它们.

openssl_random_pseudo_bytes似乎是在PHP中生成适当的随机数的推荐方式.为什么rand不使用/dev/random我不知道.

  • @MacroMan但是`openssl_random_pseudo_bytes()`*是*可移植的. (3认同)
  • rand 不使用 /dev/urandom 因为它仅在类似 posix 的环境中可用并且不可移植。 (2认同)
  • 这没有错,但我会建议您如何丢弃不需要的字符.例如,请参阅[PHP联盟的OAuth2服务器上的此拉取请求](https://github.com/thephpleague/oauth2-server/pull/273). (2认同)

Kra*_*ime 26

我知道游戏可能有点晚了,但是这里有一个简单的单行程序,可以生成一个真正的随机字符串而无需任何脚本级别循环或使用openssl库.

echo substr(str_shuffle(str_repeat('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', mt_rand(1,10))), 1, 10);
Run Code Online (Sandbox Code Playgroud)

将其分解以使参数清晰

// Character List to Pick from
$chrList = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

// Minimum/Maximum times to repeat character List to seed from
$chrRepeatMin = 1; // Minimum times to repeat the seed string
$chrRepeatMax = 10; // Maximum times to repeat the seed string

// Length of Random String returned
$chrRandomLength = 10;

// The ONE LINE random command with the above variables.
echo substr(str_shuffle(str_repeat($chrList, mt_rand($chrRepeatMin,$chrRepeatMax))), 1, $chrRandomLength);
Run Code Online (Sandbox Code Playgroud)

此方法通过随机重复字符列表,然后混合组合字符串,并返回指定的字符数来工作.

您可以通过随机化返回的字符串的长度来进一步随机化,替换$chrRandomLengthmt_rand(8, 15)(对于8到15个字符之间的随机字符串).


Dav*_*vor 25

function generateRandomString($length = 15)
{
    return substr(sha1(rand()), 0, $length);
}
Run Code Online (Sandbox Code Playgroud)

田田!

  • sha1字符串不是随机的,某些字符比其他字符更频繁地出现.在你真正想要密码等随机性的情况下使用它是不明智的. (3认同)
  • @KitSunde - 是的,sha不是随机的,rand()是随机的。sha 完全可以满足这里的需要。OP 不需要加密级别的随机性。 (2认同)

小智 24

实现此功能的更好方法是:

function RandomString($length) {
    $keys = array_merge(range(0,9), range('a', 'z'));

    $key = "";
    for($i=0; $i < $length; $i++) {
        $key .= $keys[mt_rand(0, count($keys) - 1)];
    }
    return $key;
}

echo RandomString(20);
Run Code Online (Sandbox Code Playgroud)

mt_rand更随意根据这个这个在PHP7.randfunction是别名mt_rand.


Mad*_*ota 24

PHP 7+使用random_bytes函数生成加密安全的随机字节。

$bytes = random_bytes(16);
echo bin2hex($bytes);
Run Code Online (Sandbox Code Playgroud)

可能的输出

da821217e61e33ed4b2dd96f8439056c


PHP 5.3+使用openssl_random_pseudo_bytes函数生成伪随机字节。

$bytes = openssl_random_pseudo_bytes(16);
echo bin2hex($bytes);
Run Code Online (Sandbox Code Playgroud)

可能的输出

e2d1254506fbb6cd842cd640333214ad


最好的情况下,使用

function getRandomBytes($length = 16)
{
    if (function_exists('random_bytes')) {
        $bytes = random_bytes($length / 2);
    } else {
        $bytes = openssl_random_pseudo_bytes($length / 2);
    }
    return bin2hex($bytes);
}
echo getRandomBytes();
Run Code Online (Sandbox Code Playgroud)

可能的输出

ba8cc342bdf91143


Bol*_*ock 18

$randstring在函数范围内与您调用它的范围不同.您必须将返回值分配给变量.

$randstring = RandomString();
echo $randstring;
Run Code Online (Sandbox Code Playgroud)

或者只是直接回显返回值:

echo RandomString();
Run Code Online (Sandbox Code Playgroud)

此外,在你的功能中你有一点错误.在for循环中,您需要使用,.=以便每个字符都附加到字符串.通过使用=你用每个新角色覆盖它而不是附加.

$randstring .= $characters[rand(0, strlen($characters))];
Run Code Online (Sandbox Code Playgroud)


Ja͢*_*͢ck 14

首先,定义要使用的字母表:

$alphanum = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
$special  = '~!@#$%^&*(){}[],./?';
$alphabet = $alphanum . $special;
Run Code Online (Sandbox Code Playgroud)

然后,用于openssl_random_pseudo_bytes()生成适当的随机数据:

$len = 12; // length of password
$random = openssl_random_pseudo_bytes($len);
Run Code Online (Sandbox Code Playgroud)

最后,使用此随机数据创建密码.因为每个字符$random都可以chr(0)直到chr(255),代码使用其序数值除以后的余数$alphabet_length来确保只选取字母表中的字符(注意这样做会使随机性偏差):

$alphabet_length = strlen($alphabet);
$password = '';
for ($i = 0; $i < $len; ++$i) {
    $password .= $alphabet[ord($random[$i]) % $alphabet_length];
}
Run Code Online (Sandbox Code Playgroud)

或者,通常更好的是使用RandomLibSecurityLib:

use SecurityLib\Strength;

$factory = new RandomLib\Factory;
$generator = $factory->getGenerator(new Strength(Strength::MEDIUM));

$password = $generator->generateString(12, $alphabet);
Run Code Online (Sandbox Code Playgroud)

  • 是的,新的 random_int() 函数很好:D (2认同)

Cod*_*AIK 14

function gen_uid($l=5){
   return substr(str_shuffle("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 10, $l);
}
echo gen_uid();
Run Code Online (Sandbox Code Playgroud)

默认值[5]:WvPJz

echo gen_uid(30);
Run Code Online (Sandbox Code Playgroud)

值[30]:cAiGgtf1lDpFWoVwjykNKXxv6SC4Q2


rAt*_*hus 12

这是我生成使用友好的随机密码的简单单行解决方案,不包括看起来相似的字符,例如“1”和“l”、“O”和“0”等……这里是 5 个字符,但您可以轻松当然改变它:

$user_password = substr(str_shuffle('abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ23456789'),0,5);
Run Code Online (Sandbox Code Playgroud)


Pun*_*jar 11

简短的方法..

以下是生成随机字符串的最简短方法

<?php
echo $my_rand_strng = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), -15); 

echo substr(md5(rand()), 0, 7);

echo str_shuffle(MD5(microtime()));
?>
Run Code Online (Sandbox Code Playgroud)


Put*_*nik 10

我已经测试了那里最流行的功能的性能,在我的盒子上生成1'000'000个32个符号的字符串所需的时间是:

2.5 $s = substr(str_shuffle(str_repeat($x='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($length/strlen($x)) )),1,32);
1.9 $s = base64_encode(openssl_random_pseudo_bytes(24));
1.68 $s = bin2hex(openssl_random_pseudo_bytes(16));
0.63 $s = base64_encode(random_bytes(24));
0.62 $s = bin2hex(random_bytes(16));
0.37 $s = substr(md5(rand()), 0, 32);
0.37 $s = substr(md5(mt_rand()), 0, 32);
Run Code Online (Sandbox Code Playgroud)

请注意它确实存在多长时间并不重要但速度较慢哪一个更快,因此您可以根据您的要求进行选择,包括加密准备等.

为了准确起见,添加了MD5周围的substr(),如果你需要短于32个符号的字符串.

为了回答:字符串没有连接但是被覆盖,并且没有存储函数的结果.


小智 8

一种非常快捷的方法是做一些事情:

substr(md5(rand()),0,10);
Run Code Online (Sandbox Code Playgroud)

这将生成一个长度为10个字符的随机字符串.当然,有些人可能会说它在计算方面有点沉重,但现在处理器已经过优化,可以非常快速地运行md5或sha256算法.当然,如果rand()函数返回相同的值,结果将是相同的,具有相同的1/32767几率.如果安全问题,那么只需rand()改为mt_rand()


小智 7

function rndStr($len = 64) {
     $randomData = file_get_contents('/dev/urandom', false, null, 0, $len) . uniqid(mt_rand(), true);
     $str = substr(str_replace(array('/','=','+'),'', base64_encode($randomData)),0,$len);
    return $str;
}
Run Code Online (Sandbox Code Playgroud)

  • 这不便携; 如果您尝试在任何非posix环境中运行它,它将导致致命错误. (4认同)

use*_*ond 7

这个来自于来源:

/** Get a random string
* @return string 32 hexadecimal characters
*/
function rand_string() {
    return md5(uniqid(mt_rand(), true));
}
Run Code Online (Sandbox Code Playgroud)

Adminer,用PHP编写的数据库管理工具.


小智 7

从 php7 开始,就有了 random_bytes 函数。 https://www.php.net/manual/ru/function.random-bytes.php 所以你可以生成这样的随机字符串

<?php
$bytes = random_bytes(5);
var_dump(bin2hex($bytes));
?>
Run Code Online (Sandbox Code Playgroud)


art*_*pro 6

Laravel 5框架中的Helper功能

/**
 * Generate a "random" alpha-numeric string.
 *
 * Should not be considered sufficient for cryptography, etc.
 *
 * @param  int  $length
 * @return string
 */
function str_random($length = 16)
{
    $pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

    return substr(str_shuffle(str_repeat($pool, $length)), 0, $length);
}
Run Code Online (Sandbox Code Playgroud)

  • "对于密码学等不应该被认为是足够的" 应该强调这一点. (4认同)

小智 6

来自 yii2 框架

/**
 * Generates a random string of specified length.
 * The string generated matches [A-Za-z0-9_-]+ and is transparent to URL-encoding.
 *
 * @param int $length the length of the key in characters
 * @return string the generated random key
 */

function generateRandomString($length = 10) {
    $bytes = random_bytes($length);
    return substr(strtr(base64_encode($bytes), '+/', '-_'), 0, $length);
}
Run Code Online (Sandbox Code Playgroud)


小智 5

以下是我如何获得真正唯一的随机密钥:

$Length = 10;
$RandomString = substr(str_shuffle(md5(time())), 0, $Length);
echo $RandomString;
Run Code Online (Sandbox Code Playgroud)

您可以使用 time(),因为它是 Unix 时间戳,并且与上面提到的其他随机数相比始终是唯一的。然后,您可以生成该值的 md5sum,并从生成的MD5字符串中获取所需的长度。在本例中,我使用了 10 个字符,如果我想让它更加独特,我可以使用更长的字符串。

我希望这有帮助。

  • 当然,“time()”远非唯一:它会一次又一次返回相同的值,直到当前秒结束。这里真正提供一些随机性的是“str_shuffle()”——其余的代码只是减少了从中挑选字符的样本。 (2认同)
  • 攻击者可以猜测“time()”返回的值(它只是一个时间戳),它是一个弱随机性来源。 (2认同)

kas*_*mir 5

另一种单行代码,生成包含字母和数字的 10 个字符的随机字符串。它将创建一个数组range(调整第二个参数来设置大小),循环遍历该数组并分配一个随机 ASCII 字符(范围 0-9 或 az),然后内爆该数组以获取字符串。

$str = implode('', array_map(function () { return chr(rand(0, 1) ? rand(48, 57) : rand(97, 122)); }, range(0, 9)));
Run Code Online (Sandbox Code Playgroud)

注意:这仅适用于 PHP 5.3 及更高版本


Jac*_*ith 5

一艘班轮。

对于具有某些独特性的大型字符串来说速度很快。

function random_string($length){
    return substr(str_repeat(md5(rand()), ceil($length/32)), 0, $length);
}
Run Code Online (Sandbox Code Playgroud)


Anj*_*K P 5

function randomString($length = 5) {
    return substr(str_shuffle(implode(array_merge(range('A','Z'), range('a','z'), range(0,9)))), 0, $length);
}
Run Code Online (Sandbox Code Playgroud)


sxn*_*sxn 5

/**
 * @param int $length
 * @param string $abc
 * @return string
 */
function generateRandomString($length = 10, $abc = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
{
    return substr(str_shuffle($abc), 0, $length);
}
Run Code Online (Sandbox Code Playgroud)

来自http://www.xeweb.net/2011/02/11/generate-a-random-string-az-0-9-in-php/