如何使用PHP创建随机字符串?

Kei*_*gan 57 php string random

我知道PHP中的rand函数会生成随机整数,但生成随机字符串的最佳方法是:

原始字符串,9个字符

$string = 'abcdefghi';
Run Code Online (Sandbox Code Playgroud)

示例随机字符串限制为6个字符

$string = 'ibfeca';
Run Code Online (Sandbox Code Playgroud)

更新:我发现了大量这些类型的函数,基本上我正试图理解每一步背后的逻辑.

更新:该函数应根据需要生成任意数量的字符.

如果您回复,请评论部分.

Gum*_*mbo 98

如果要允许重复出现的字符,可以使用此功能:

function randString($length, $charset='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')
{
    $str = '';
    $count = strlen($charset);
    while ($length--) {
        $str .= $charset[mt_rand(0, $count-1)];
    }
    return $str;
}
Run Code Online (Sandbox Code Playgroud)

基本算法是生成< length >次0和< 字符数之间的随机数> - 1我们用作索引从我们的集合中选择一个字符并连接这些字符.0和< 字符数 > - 1个边界表示$charset字符串的边界,因为第一个字符被寻址,$charset[0]而最后一个字符用$charset[count($charset) - 1].

  • 喜欢这种方式,它比接受的解决方案更好,尽可能简单,但你应该通过从循环中删除$ count-1并将其放在上面来最小化它:$ count = strlen($ charset) - 1; (6认同)

Cha*_*rch 92

好吧,你没有澄清我在评论中提出的所有问题,但我会假设你想要一个可以带一串"可能"字符和一串字符串返回的函数.为清楚起见,根据要求进行了彻底评论,使用了比我通常更多的变量:

function get_random_string($valid_chars, $length)
{
    // start with an empty random string
    $random_string = "";

    // count the number of chars in the valid chars string so we know how many choices we have
    $num_valid_chars = strlen($valid_chars);

    // repeat the steps until we've created a string of the right length
    for ($i = 0; $i < $length; $i++)
    {
        // pick a random number from 1 up to the number of valid chars
        $random_pick = mt_rand(1, $num_valid_chars);

        // take the random character out of the string of valid chars
        // subtract 1 from $random_pick because strings are indexed starting at 0, and we started picking at 1
        $random_char = $valid_chars[$random_pick-1];

        // add the randomly-chosen char onto the end of our string so far
        $random_string .= $random_char;
    }

    // return our finished random string
    return $random_string;
}
Run Code Online (Sandbox Code Playgroud)

要使用示例数据调用此函数,您可以将其称为:

$original_string = 'abcdefghi';
$random_string = get_random_string($original_string, 6);
Run Code Online (Sandbox Code Playgroud)

请注意,此函数不会检查传递给它的有效字符的唯一性.例如,如果您使用有效的字符串字符串来调用它'AAAB',那么为每个字母选择A作为B的可能性要高三倍.根据您的需要,可以将其视为错误或功能.

  • **警告**:此代码不安全,因为它依赖于`[mt_rand()`,它[容易受到多次攻击](http://phpsecurity.readthedocs.org/en/latest/Insufficient-Entropy-For-Random- Values.html) (12认同)

tas*_*ski 52

我的最爱:

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

  • 好吧,它对于拉斯维加斯赌场的机器来说还不够好,但足以产生注册密钥(例如),这在网站上有效30分钟. (22认同)
  • 单线方法的+1,当只需要一个没有NSA安全协议的简单随机字符串时 (2认同)

irc*_*ell 24

所以,让我先说一下USE A LIBRARY.许多存在:

问题的核心几乎是本页面中的每个答案都容易受到攻击.mt_rand(),rand(),lcg_value()uniqid()容易受到攻击.

一个好的系统将使用/dev/urandom文件系统,或mcrypt_create_iv()(with MCRYPT_DEV_URANDOM)或openssl_pseudo_random_bytes().以上所有都做了.PHP 7 将提供两个新功能 random_bytes($len),random_int($min, $max)这也是安全的.

请注意,大多数这些函数(除外random_int())都返回"原始字符串",这意味着它们可以包含任何ASCII字符0 - 255.如果你想要一个可打印的字符串,我建议你运行结果base64_encode().


小智 17

function generate_random_string($name_length = 8) {
    $alpha_numeric = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    return substr(str_shuffle(str_repeat($alpha_numeric, $name_length)), 0, $name_length);
}
Run Code Online (Sandbox Code Playgroud)

在下面的评论中根据mzhang的伟大建议更新了代码.

  • 我真的很喜欢这个解决方案,但我可以解决@ChadBirch和@ ceejayoz的问题 - 而不是`str_shuffle($ alpha_numeric)`,只需使用`str_shuffle(str_repeat($ alpha_numeric,$ name_length))`; `str_repeat`生成一个重复"n"次的字符串 - 这允许未抽取字符串中每个字母的`n`个实例,允许'AAAA ...'作为最终输出的可能性. (8认同)
  • "更新:该功能应根据需要生成任何数量的字符." - 此功能最大长度为62. (4认同)
  • 另外,它不是随机的 - 使用这种方法在结果字符串中只能有一个字符.一个真正随机的算法会产生'可能性*',导致'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',但不太可能. (4认同)
  • 那范围蠕变,即时通讯呼唤恶作剧! (4认同)

Sli*_*liq 9

@ taskamiski的更好和更新版本的优秀答案:

更好的版本,使用mt_rand()而不是rand():

echo md5(mt_rand()); // 32 char string = 128bit
Run Code Online (Sandbox Code Playgroud)

更好的是,对于更长的字符串,使用hash()允许选择散列算法的函数:

echo hash('sha256', mt_rand()); // 64 char string
echo hash('sha512', mt_rand()); // 128 char string
Run Code Online (Sandbox Code Playgroud)

如果你想减少结果让我们说50个字符,那就这样做:

echo substr(hash('sha256', mt_rand()), 0, 50); // 50 char string
Run Code Online (Sandbox Code Playgroud)


Imr*_*ran 6

最后加入字符应该比重复字符串连接更有效.

编辑#1:添加选项以避免字符重复.

编辑#2:如果选择了$ norepeat并且$ len大于要选择的字符集,则抛出异常以避免进入无限循环.

编辑#3:当选择$ norepeat时,使用数组键存储拾取的随机字符,因为关联数组键查找比线性搜索数组更快.

function rand_str($len, $norepeat = true)
{
    $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    $max = strlen($chars) - 1;

    if ($norepeat && len > $max + 1) {
        throw new Exception("Non repetitive random string can't be longer than charset");
    }

    $rand_chars = array();

    while ($len) {
        $picked = $chars[mt_rand(0, $max)];

        if ($norepeat) {
            if (!array_key_exists($picked, $rand_chars)) {
                $rand_chars[$picked] = true;
                $len--;
            }
        }
        else {
            $rand_chars[] = $picked;
            $len--;
        }
    }

    return implode('', $norepeat ? array_keys($rand_chars) : $rand_chars);   
}
Run Code Online (Sandbox Code Playgroud)