如果参数相同,如何在php中生成相同的随机值?

时间:2019-05-05 08:01:15

标签: php

我正在使用一个函数来使用TAG生成随机值,其中包括以下参数:长度,随机类型:字母,数字或混合,以及小写,大写。 现在的问题是,我想存储或保存,修复或冻结一个随机结果,以便在多个地方使用它。 例如,我使用FixRAND,而不是RAND,那么只要TAG具有相同的参数,结果在整个页面中将是相同的。

让您对我已经拥有的东西有一个小小的了解。当我使用[TAG,10,A,U]之类的TAG时,它是完全可用的,但是每次都会生成随机值。我需要添加另一个TAG,该TAG可以存储在相同请求下相同结果的方式。

function generateRandom($length,$type,$gen){
        switch ($type) {
            case 'A':
                $rd= "";
                srand((double)microtime()*1000000);
                $data = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ";
                for($i = 0; $i < $length; $i++){
                    $rd .= substr($data, (rand()%(strlen($data))), 1);
                }
                break;
            case 'N':
                $rd= "";
                srand((double)microtime()*1000000);
                $data = '0123456789';
                for($i = 0; $i < $length; $i++){
                    $rd .= substr($data, (rand()%(strlen($data))), 1);
                }
                break;
            case 'M':
                $rd= "";
                srand((double)microtime()*1000000);
                $data = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789";
                for($i = 0; $i < $length; $i++){
                    $rd .= substr($data, (rand()%(strlen($data))), 1);
                }

                break;
        }
        if ( $gen == 'U') $rd = strtoupper($rd);
        if ( $gen == 'L') $rd = strtolower($rd);
        return $rd;
    }

$replaced_xxxxxx=str_replace("[MESSAGE]","$message",$replaced_xxxxxx);
preg_match_all("/\[RAND,[0-9]+,[AMN],[LU]\]/",$replaced_xxxxxx,$random_tag_array);
        foreach ($random_tag_array[0] as $random_tag) {
            $random_stripped=$random_tag;
            $random_stripped=str_replace("[RAND,","",$random_stripped);
            $random_stripped=str_replace("]","",$random_stripped);
            $random_exploded=explode(',', $random_stripped);
            $random_generated=generateRandom($random_exploded[0],$random_exploded[1],$random_exploded[2]);
            $replaced_xxxxxx=preg_replace($random_tag, $random_generated, $replaced_xxxxxx,1);

1 个答案:

答案 0 :(得分:1)

编辑:正如@KIKOSoftware指出的那样,我的回答不是真正的随机性。我修改了答案。现在,它使用random_int()来加密加密的伪随机。现在将随机函数的结果与输入参数一起保存。这是唯一的方法,因为random_int() 是随机的。这样就无法再次创建相同的值,因此必须保存它们。

此解决方案需要更多的内存,因为它需要保存更多的值。但这是随机的。您可以选择两种解决方案。如果您尝试获取随机示例,则原始解决方案就足够了。对于需要安全处理的事情(例如密码处理等),您应该使用新的解决方案。

注意:需要PHP 7 + 。如果您使用的是较低版本,则php.net in the comments上将提供反向移植功能。

function generateRandom($length, $type, $gen){
    switch ($type){
        case 'A':
            $data = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ";
            break;
        case 'N':
            $data = '0123456789';
            break;
        case 'M':
            $data = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789";
            break;
        default: 
            $data = "";
            break;
    }

    static $randoms = array();

    $rd = "";
    $max = strlen($data) - 1;
    for($i = 0; $i < $length; $i++){
        $rd_key = $length.$type.$gen.$i;
        if(!isset($randoms[$rd_key])){
            $randoms[$rd_key] = random_int(0, $max);
        }
        $rd .= $data[$randoms[$rd_key]];
    }

    if ( $gen == 'U') $rd = strtoupper($rd);
    if ( $gen == 'L') $rd = strtolower($rd);

    return $rd;
}

示例结果

enter image description here

使用代码生成:

print("<table>".
        "<tr>".
            "<th>Function</th>".
            "<th>Secure result</th>".
            "<th>Secure is correct</th>".
            "<th>Normal result</th>".
            "<th>Normal is correct</th>".
        "</tr>");
$cache_normal = array();
$cache_secure = array();
// 12 possibilities, there has to be one double element
for($i = 0; $i < 13; $i++){
    $length = rand(3, 5);
    $type = rand(0, 2);
    switch($type){
        case 1: $type = "N"; break;
        case 2: $type = "M"; break;
        case 0: 
        default: $type = "A"; break;
    }
    $gen = rand(0, 1);
    switch($gen){
        case 1: $gen = "U"; break;
        case 0: 
        default: $gen = "L"; break;
    }

    $secure = generateRandomSecure($length, $type, $gen);

    if(!isset($cache_secure[$length.$type.$gen])){
        $cache_secure[$length.$type.$gen] = $secure;
        $secure_corr = "-";
    }
    elseif($cache_secure[$length.$type.$gen] == $secure){
        $secure_corr = "<i>found and correct</i>";
    }
    else{
        $secure_corr = "<i>found but wrong</i>";
    }

    $normal = generateRandom($length, $type, $gen);
    if(!isset($cache_normal[$length.$type.$gen])){
        $cache_normal[$length.$type.$gen] = $normal;
        $normal_corr = "-";
    }
    elseif($cache_normal[$length.$type.$gen] == $normal){
        $normal_corr = "<i>found and correct</i>";
    }
    else{
        $normal_corr = "<i>found but wrong</i>";
    }

    print("<tr>".
            "<td><code>generateRandom(".$length.", ".$type.", ". $gen.")</code></td>".
            "<td>'".$secure."'</td>".
            "<td>".$secure_corr."</td>".
            "<td>'".$normal."'</td>".
            "<td>".$normal_corr."</td>".
        "</tr>"
    );
}
print("</table>");

原始答案:我想我会存储随机数的种子。您可以使用包含参数作为键和种子作为值的静态(或全局)变量。

function generateRandom($length, $type, $gen){
    static $seeds = array();
    if(!isset($seeds[$length.$type.$gen])){
        $seeds[$length.$type.$gen] = microtime(true) * 1000000;
    }
    srand($seeds[$length.$type.$gen]);
    $rd = "";

    switch ($type) {
        case 'A':
            $data = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ";
            break;
        case 'N':
            $data = '0123456789';
            break;
        case 'M':
            $data = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789";
            break;
        default: 
            $data = "";
            break;
    }

    $len = strlen($data);
    for($i = 0; $i < $length; $i++){
       $rd .= $data[rand() % $len];
    }

    if ( $gen == 'U') $rd = strtoupper($rd);
    if ( $gen == 'L') $rd = strtolower($rd);

    return $rd;
}

此代码导致以下结果。我希望这是您想要做的:

var_dump(generateRandom(3, "A", "L")); // prints e.g. string(3) "wkr"
var_dump(generateRandom(4, "A", "L")); // prints e.g. string(3) "rppd"
var_dump(generateRandom(4, "N", "L")); // prints string(4) "9377"
var_dump(generateRandom(3, "A", "L")); // prints string(3) "wkr" again

重新加载后,所有值再次不同(因为种子改变了)。