【问题标题】:Generate random 5 characters string生成随机 5 个字符的字符串
【发布时间】:2011-07-23 06:21:24
【问题描述】:

我想创建精确的 5 个随机字符串,并且重复的可能性最小。最好的方法是什么?谢谢。

【问题讨论】:

标签: php random


【解决方案1】:

包含特殊字符的简单一行:

echo implode("", array_map(function() {return chr(mt_rand(33,126));}, array_fill(0,5,null)));

基本上,它用空值填充长度为 5 的数组,并用 ascii 范围中的随机符号替换每个值,最后,它将它们连接在一起形成一个字符串。

使用第二个array_fill参数来控制长度。

它使用 33 到 126 的 ASCII 表范围,其中包括以下字符:

!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

【讨论】:

    【解决方案2】:

    在我想到使用 PHP array 之前,我也不知道该怎么做。而且我很确定这是使用数组生成随机字符串或数字的最简单方法。代码:

    function randstr ($len=10, $abc="aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789") {
        $letters = str_split($abc);
        $str = "";
        for ($i=0; $i<=$len; $i++) {
            $str .= $letters[rand(0, count($letters)-1)];
        };
        return $str;
    };
    

    你可以这样使用这个功能

    randstr(20)     // returns a random 20 letter string
                    // Or like this
    randstr(5, abc) // returns a random 5 letter string using the letters "abc"
    

    【讨论】:

      【解决方案3】:

      你可以这样尝试:

      $length = 5;
      
      $randomletter = substr(str_shuffle("abcdefghijklmnopqrstuvwxyz"), 0, $length);
      

      更多详情:http://forum.arnlweb.com/viewtopic.php?f=7&t=25

      【讨论】:

        【解决方案4】:
        function CaracteresAleatorios( $Tamanno, $Opciones) {
            $Opciones = empty($Opciones) ? array(0, 1, 2) : $Opciones;
            $Tamanno = empty($Tamanno) ? 16 : $Tamanno;
            $Caracteres=array("0123456789","abcdefghijklmnopqrstuvwxyz","ABCDEFGHIJKLMNOPQRSTUVWXYZ");
            $Caracteres= implode("",array_intersect_key($Caracteres, array_flip($Opciones)));
            $CantidadCaracteres=strlen($Caracteres)-1;
            $CaracteresAleatorios='';
            for ($k = 0; $k < $Tamanno; $k++) {
                $CaracteresAleatorios.=$Caracteres[rand(0, $CantidadCaracteres)];
            }
            return $CaracteresAleatorios;
        }
        

        【讨论】:

        • 专业提示 - 包括一些关于您的答案如何解决 OP 问题的解释,以及为什么它可能与已经提供的其他答案不同。
        【解决方案5】:

        以下内容应提供最少的重复机会(您可能希望将 mt_rand() 替换为更好的随机数源,例如来自 /dev/*random 或来自 GUID):

        <?php
            $characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
            $result = '';
            for ($i = 0; $i < 5; $i++)
                $result .= $characters[mt_rand(0, 61)];
        ?>
        

        编辑:
        如果您真的担心安全问题,请不要使用rand()mt_rand(),并验证您的随机数据设备实际上是生成随机数据的设备,而不是常规文件或可预测的文件,例如 /dev/zeromt_rand() 被认为是有害的:
        https://spideroak.com/blog/20121205114003-exploit-information-leaks-in-random-numbers-from-python-ruby-and-php

        编辑: 如果你在 PHP 中支持 OpenSSL,你可以使用openssl_random_pseudo_bytes():

        <?php
            $length = 5;
            $randomBytes = openssl_random_pseudo_bytes($length);
            $characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
            $charactersLength = strlen($characters);
            $result = '';
            for ($i = 0; $i < $length; $i++)
                $result .= $characters[ord($randomBytes[$i]) % $charactersLength];
        ?>
        

        【讨论】:

        • 第一个例子更聪明,$result .= $characters[mt_rand(0, strlen($characters)-1)]
        • 在这种情况下,您应该事先确定长度并将其至少存储在一个变量中。在循环中使用strlen() 是不必要的开销,特别是如果您已经知道字符集在此期间不会更改。
        • 我对此表示怀疑,php已经过优化,无论如何它是一个选项:)
        【解决方案6】:

        似乎 str_shuffle 对此很有用。 用您想要的任何字符播种随机播放。

        $my_rand_strng = substr(str_shuffle("ABCDEFGHIJKLMNOPQRSTUVWXYZ"), -5);
        
        【解决方案7】:

        我已经用这个了:

        <?php function fRand($len) {
            $str = '';
            $a = "abcdefghijklmnopqrstuvwxyz0123456789";
            $b = str_split($a);
            for ($i=1; $i <= $len ; $i++) { 
                $str .= $b[rand(0,strlen($a)-1)];
            }
            return $str;
        } ?>
        

        当你调用它时,设置字符串的长度。

        <?php echo fRand([LENGHT]); ?>
        

        您还可以更改字符串$a 中可能出现的字符。

        【讨论】:

        • 我看到浪费时间无所事事地开发这个功能。我google了一下! @安德鲁
        【解决方案8】:

        这是我的random 5 cents ...

        $random=function($a, $b) {
            return(
                substr(str_shuffle(('\\`)/|@'.
                password_hash(mt_rand(0,999999),
                PASSWORD_DEFAULT).'!*^&~(')),
                $a, $b)
            );
        };
        
        echo($random(0,5));
        

        PHP 的新password_hash() (* >= PHP 5.5) 函数可以生成相当长的大小写字符和数字集。

        两个连接。 $random 函数内password_hash 前后的字符串适合更改。

        $random() *($a,$b) 的参数实际上是 substr() 参数。 :)

        注意:这不需要是一个函数,它也可以是普通变量.. 作为一个讨厌的单线,像这样:

        $random=(substr(str_shuffle(('\\`)/|@'.password_hash(mt_rand(0,999999), PASSWORD_DEFAULT).'!*^&~(')), 0, 5));
        
        echo($random);
        

        【讨论】:

          【解决方案9】:
          $str = '';
          $str_len = 8;
          for($i = 0, $i < $str_len; $i++){
              //97 is ascii code for 'a' and 122 is ascii code for z
              $str .= chr(rand(97, 122));
          }
          return $str
          

          【讨论】:

            【解决方案10】:

            来源:PHP Function that Generates Random Characters

            这个简单的 PHP 函数对我有用:

            function cvf_ps_generate_random_code($length=10) {
            
               $string = '';
               // You can define your own characters here.
               $characters = "23456789ABCDEFHJKLMNPRTVWXYZabcdefghijklmnopqrstuvwxyz";
            
               for ($p = 0; $p < $length; $p++) {
                   $string .= $characters[mt_rand(0, strlen($characters)-1)];
               }
            
               return $string;
            
            }
            

            用法:

            echo cvf_ps_generate_random_code(5);
            

            【讨论】:

              【解决方案11】:

              一种快速的方法是使用uniqid 函数中最不稳定的字符。

              例如:

              $rand = substr(uniqid('', true), -5);
              

              【讨论】:

              • -5 的长度是真的吗?
              • @gumuruh 问题是“...创建精确的 5 个随机字符串...”,因此将 -5 作为偏移量参数传递给 substr 将使用字符串中的 last 五个字符.根据 PHP 文档……“如果 offset 为负,则返回的字符串将从字符串末尾的第 offset 个字符开始。”
              【解决方案12】:
              $rand = substr(md5(microtime()),rand(0,26),5);
              

              这是我最好的猜测——除非你也在寻找特殊字符:

              $seed = str_split('abcdefghijklmnopqrstuvwxyz'
                               .'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
                               .'0123456789!@#$%^&*()'); // and any other characters
              shuffle($seed); // probably optional since array_is randomized; this may be redundant
              $rand = '';
              foreach (array_rand($seed, 5) as $k) $rand .= $seed[$k];
              

              Example

              并且,对于基于时钟的一个(因为它是增量的,所以冲突更少):

              function incrementalHash($len = 5){
                $charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
                $base = strlen($charset);
                $result = '';
              
                $now = explode(' ', microtime())[1];
                while ($now >= $base){
                  $i = $now % $base;
                  $result = $charset[$i] . $result;
                  $now /= $base;
                }
                return substr($result, -5);
              }
              

              注意:增量意味着更容易猜测;如果您将其用作盐或验证令牌,请不要。 “WCWyb”的盐(现在)意味着5秒后它是“WCWyg”)

              【讨论】:

              • 然而,使用md5() 的问题是你得到一个由16 个字符集组成的字符串(10 位数字和af,即每个字符串字符4 位)。这对于某些目的可能已经足够,但对于加密目的可能太少了(16 个符号中的 5 个字符 = 16^5 = 20 位 = 1048576 种可能性)。
              • array_rand($seed, 5) 将返回数组键,而不是值,因此您的代码将不起作用
              • 我认为使用加密哈希函数来生成随机字符至少是不合适的。
              • 是否也可以在$charset 中包含"' 和反斜杠?我需要使用转义序列来包含这些字符吗?
              • 第二个 sn-p 甚至没有使用$len 输入参数...你忘记了吗?
              【解决方案13】:

              PHP (php 5.4.4) 中工作正常

              $seed = str_split('abcdefghijklmnopqrstuvwxyz');
              $rand = array_rand($seed, 5);
              $convert = array_map(function($n){
                  global $seed;
                  return $seed[$n];
              },$rand);
              
              $var = implode('',$convert);
              echo $var;
              

              Live Demo

              【讨论】:

                【解决方案14】:

                如果你只得到字母 A-F 没问题,那么这是我的解决方案:

                str_pad(dechex(mt_rand(0, 0xFFFFF)), 5, '0', STR_PAD_LEFT);
                

                我认为对于生成一系列随机十六进制数字这样简单的任务来说,使用散列函数是一种过度杀伤力。 dechex + mt_rand 将做同样的工作,但没有不必要的加密工作。 str_pad 保证输出字符串长度为 5 个字符(如果随机数小于 0x10000)。

                重复概率取决于mt_rand 的可靠性。 Mersenne Twister 以高质量的随机性而闻名,因此它应该非常适合任务。

                【讨论】:

                  【解决方案15】:

                  类似于Brad Christie 的答案,但对字符0-9a-zA-Z 使用sha1 算法并以随机值作为前缀:

                  $str = substr(sha1(mt_rand() . microtime()), mt_rand(0,35), 5);
                  

                  但是如果你设置了一个定义的(允许的)字符:

                  $validChars = array('0','1','2' /*...*/,'?','-','_','a','b','c' /*...*/);
                  $validCharsCount = count($validChars);
                  
                  $str = '';
                  for ($i=0; $i<5; $i++) {
                      $str .= $validChars[rand(0,$validCharsCount - 1)];
                  }
                  

                  ** 更新 **

                  正如Archimedix 指出的那样,这不能保证返回“被重复的可能性最小”,因为给定字符范围的组合数量很少。您要么需要增加字符数,要么在字符串中允许额外(特殊)字符。我认为,在你的情况下,第一个解决方案会更好。

                  【讨论】:

                  • 使用 time() 的可预测性是 microtime() 的 100 万倍。
                  • 还请注意我对 Brad 的回答的 cmets,更大的问题是生成的哈希是由 16 个有效字符组成的十六进制表示,因此 $str 仅留下 1024 个变体。
                  • @Archimedix,也许,但 OP 没有要求安全,问题被定义为具有由 5x26 个不同字符的组合组成的字符串生成算法,并避免重复。这可能是用于注册过程(或计费过程)中的确认参考号或其他内容
                  • 据我了解,他确实要求重复的可能性最小,这有 0.1% 的概率(1024 分之一)可以几乎是十亿分之一。
                  • 但是,如果您需要生成 5 个字符的参考密钥并给您一个客户/客户,您不想仅仅因为它更安全而给他们“˫§»⁋⅓”。 . 您将参考键增加到 7 个或更多字符。 (顺便说一句:在我之前的评论中更正,它是 5x36 个字符)
                  【解决方案16】:

                  如果for 循环供不应求,这就是我喜欢使用的:

                  $s = substr(str_shuffle(str_repeat("0123456789abcdefghijklmnopqrstuvwxyz", 5)), 0, 5);
                  

                  【讨论】:

                  • 有趣的解决方案...非常简洁,但我想知道这是否比使用 for 更快或更慢。虽然不能打扰基准:-)
                  • @matthew str_shuffle 将不断产生重复
                  • @user2826057: str_shuffle('ab') 会给出abba,但绝不会给出aa。添加str_repeat 允许这样做。但话虽如此,我给出的解决方案并不是一个真正的解决方案......虽然它确实有效。
                  • 假设 RNG 是均匀分布的,发生这种情况的可能性为 1/60466176。
                  • 这非常适合我们生成凭证代码的用例。我们删除了混淆字符,例如 li10O 等,并且在 500 张优惠券中没有重复。
                  【解决方案17】:

                  我总是为此使用相同的功能,通常是生成密码。它易于使用且有用。

                  function randPass($length, $strength=8) {
                      $vowels = 'aeuy';
                      $consonants = 'bdghjmnpqrstvz';
                      if ($strength >= 1) {
                          $consonants .= 'BDGHJLMNPQRSTVWXZ';
                      }
                      if ($strength >= 2) {
                          $vowels .= "AEUY";
                      }
                      if ($strength >= 4) {
                          $consonants .= '23456789';
                      }
                      if ($strength >= 8) {
                          $consonants .= '@#$%';
                      }
                  
                      $password = '';
                      $alt = time() % 2;
                      for ($i = 0; $i < $length; $i++) {
                          if ($alt == 1) {
                              $password .= $consonants[(rand() % strlen($consonants))];
                              $alt = 0;
                          } else {
                              $password .= $vowels[(rand() % strlen($vowels))];
                              $alt = 1;
                          }
                      }
                      return $password;
                  }
                  

                  【讨论】:

                  • 不错的代码。但是 $alt 总是从 1 翻转到 0。改为随机化 $alt 不是更好吗?
                  猜你喜欢
                  • 1970-01-01
                  • 2023-03-27
                  • 1970-01-01
                  • 2017-08-01
                  • 2011-06-30
                  • 2014-02-09
                  相关资源
                  最近更新 更多