功能未在每次通话时重新评估

时间:2016-02-16 20:57:14

标签: php function echo 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;
}

1 个答案:

答案 0 :(得分:1)

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

通过切换到连接,$formIdrandString(16)实际上都会发挥作用,time()相同的事实不会成为问题。每次调用newCSRF()时,您都会得到不同的结果(假设$formId不同)。

简而言之,解决方案是将$c_ip + $formId + time() + randString(16)更改为$c_ip . $formId . time() . randString(16)