为什么str_shuffle总是生成类似的模式?

时间:2014-04-03 10:28:13

标签: php string shuffle secret-key

我正在尝试使用以下代码生成1500个身份验证代码:

    <?php
include "../include/top.php";

set_time_limit(0);
ini_set("memory_limit", "-1");

$end=0;
while ($end<1500)
{
//generate an authentication code
$string="ABCDEFGHJKLMNPQRSTUVWXYZ123456789";
$string= substr(str_shuffle($string),5,8) ;

//check whether generated code already exist
$query = "select count(*) from auth where code = '$string' ";
$stmt = prepare ($query);
execute($stmt);
$bind = mysqli_stmt_bind_result($stmt, $count);
check_bind_result($bind);
mysqli_stmt_fetch($stmt);
mysqli_stmt_free_result($stmt);

//If generated code does not already exist, insert it to Database table
if ($count == 0)
    {
    echo $string."<br>";
    $query = "insert into auth (Code) values ('$string')";
    $stmt = prepare ($query);
    execute($stmt);
    $end++;
    }
}
?>

它在数据库中生成并插入1024个代码,并在15秒内在浏览器中打印667个代码,浏览器继续加载而不插入/打印更多代码,直到我在半小时后关闭浏览器窗口。 之后,当从WAMP打开浏览器中的任何网页时,它显示浏览器正在加载并且不显示内容。也就是说,我需要在打开任何网页之前运行此脚本后重新启动WAMP。 我已经尝试了很多次。

为什么脚本不会生成1500个代码并且在达到计数667/1024时总是停止?

更新

作为一个实验,我在IF条件中添加了一个ELSE子句,并编写了代码来打印&#34; Code Already Exist&#34;在ELSE条款中。并使用同一个表的空(截断)副本运行脚本,然后打印并插入1024个代码,然后打印&#34; Code Already Exist&#34;连续(在5分钟内继续进行大约70万以上的参赛作品)。再次使用只有1024行的表运行脚本时,它甚至不会打印或插入单个代码。相反,它无限继续打印&#34;代码已经存在&#34;。 我观察到的另一件事是WHILE循环的第一次1024次迭代通过IF条件(如果表为空)。并且所有后续迭代都失败了IF条件。

3 个答案:

答案 0 :(得分:2)

我不认为str_shuffle中的随机数字符合这一点。

如果我运行它,一旦我获得1024个唯一代码,然后它只生成重复。如果我然后重新启动它,它将生成另外976个唯一代码,在数据库上总共提供2000个代码。

因此,我假设str_shuffle()使用的随机数需要重置才能完成所需的1500个唯一代码的生成。

尝试这个小修改,它至少会在15000次尝试生成唯一代码失败后停止执行。

基本上我认为你必须提出一个更好的随机化机制。

<?php
include "../include/top.php";

set_time_limit(0);
ini_set("memory_limit", "-1");

$end=0;
$dups=0;
while ($end<1500 && $dups < 15000)
{
    //generate an authentication code
    $string="ABCDEFGHJKLMNPQRSTUVWXYZ123456789";
    $string= substr(str_shuffle($string),5,8) ;

    //check whether generated code already exist
    $query = "select count(*) from auth where code = '$string' ";
    $stmt = prepare ($query);
    execute($stmt);
    $bind = mysqli_stmt_bind_result($stmt, $count);
    check_bind_result($bind);
    mysqli_stmt_fetch($stmt);
    mysqli_stmt_free_result($stmt);

    //If generated code does not already exist, insert it to Database table
    if ($count == 0) {
        echo $string."<br>";
        $query = "insert into auth (Code) values ('$string')";
        $stmt = prepare ($query);
        execute($stmt);
        $end++;
    } else {
        $dups++
        echo "DUPLICATE for $string, Dup Count = $dups<br>";
    }
}
?>

为什么你需要重启=你设置php超时,所以它永远不会超时。

答案 1 :(得分:1)

我没有看到任何特定的编码错误。使用str_shuffle创建身份验证代码是特殊的,因为它可以防止重复的字母,从而使可能的范围小得多。所以它可能只是重复模式。

尝试这样的事情,这样你就可以改组洗牌的字符串:

$origstring= str_shuffle("ABCDEFGHJKLMNPQRSTUVWXYZ123456789");

while ($end<1500 && $dups < 15000)
{
   $origstring = str_shuffle( $origstring);
   $string = substr( $newstring, 5, 8);

或者,使用类似的东西生成字符串,以便您可以重复,创建更大范围的可能值:

   $characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
   for ($i = 0; $i < 8; $i++)
   {
      $code .= $characters[mt_rand(0, 35)];
   }

答案 2 :(得分:0)

您必须微调php.ini配置文件中的一些变量,找到它们:

; Maximum execution time of each script, in seconds
; http://php.net/max-execution-time
; Note: This directive is hardcoded to 0 for the CLI SAPI
max_execution_time = 600    

而且,不是强制性的,你也可以改变它们:

suhosin.post.max_vars = 5000   
suhosin.request.max_vars = 5000

修改后,重新启动Web服务器。