函数不会在每次调用时重新评估

function not reevaluated on each call

好的,我有一个函数:newCSRF($formID);生成一个我在表单中调用的 CSRF 令牌。像这样

if(){
    echo "<some html form>". newCSRF("login-form")."<rest of html>";
}

在同一 index.php 页面上还有另一种形式

if(){
    echo "<some html form>". newCSRF("register-form")."<rest of html>";
}

那些 csrf 令牌应该是不同的(我已经检查过 newCSRF() 没有任何问题。但它们不是...... 如果我将它们写成:

来证明它应该有效
echo "<some html form>"; echo newCSRF("register-form"); echo "<rest of html>";

效果非常好。我的第一个拼写有什么问题??我不喜欢第二个,我觉得很奇怪。

编辑 添加了 newCSRF():

function newCSRF($formId)
{
    $c_ip = $_SERVER['REMOTE_ADDR']; //gets the client IPv4 address

    //generates a unique security token, randString has been added beacuse of dupes when refresh spamming.
    //$csrf = dechex(crc32($c_ip."".$formId."".time()."".randString(16)));
    $csrf = hash("crc32", $c_ip + $formId + time() + randString(16));

    try
    {
        $pdo_options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_EXCEPTION;

        //connecting to the sql server
        $bdd = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME, DB_USER, DB_PASSWORD, $pdo_options);

        $a = $bdd->prepare('INSERT INTO csrf (form_id, client_ip, token, expire) VALUES(:form, :ip, :csrf, :expi)');

        $a->execute(array(
                'form'  => ichar($formId),
                'ip'    => $c_ip,
                'csrf'  => $csrf,
                'expi'  => time() + 1800)); //CSRF token remains valid for 15 min.
        $bdd = null;
        log_write("New CSRF token successfuly created", 0, false);
    }
    catch (PDOException $e)
    {
        log_write("Error occured when creating new CSRF token", 3, false);
        log_write("in File: " . __FILE__ . " on line: " . __LINE__ . " : " . $e->getMessage(), 3, false);
        $bdd = null;
        exit(1);
    }
    return $csrf;
}

就您获得相同价值的原因而言,这里有几个因素在起作用。首先,您对 newCSRF() 的两次调用可能足够接近,以至于当您在每个调用中调用 time() 时,您将获得相同的值。其次,虽然您没有在这里显示它的内容,但我的猜测是 randString() returns(顾名思义)是一个文本字符串。由于您进行的是数学加法而不是串联,因此 $formIdrandString(16) 中的文本字符串在从每次调用中获取不同值方面确实无济于事。由于 time() 在两个调用中相同,因此每次调用的整个计算在数学上是等效的。

通过切换到串联,$formIdrandString(16) 都将实际发挥作用,并且 time() 相同这一事实将不成问题。每次调用 newCSRF() 都会得到不同的结果(假设 $formId 不同)。

总之就是把$c_ip + $formId + time() + randString(16)改成$c_ip . $formId . time() . randString(16)