函数不会在每次调用时重新评估
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(顾名思义)是一个文本字符串。由于您进行的是数学加法而不是串联,因此 $formId
和 randString(16)
中的文本字符串在从每次调用中获取不同值方面确实无济于事。由于 time()
在两个调用中相同,因此每次调用的整个计算在数学上是等效的。
通过切换到串联,$formId
和 randString(16)
都将实际发挥作用,并且 time()
相同这一事实将不成问题。每次调用 newCSRF()
都会得到不同的结果(假设 $formId
不同)。
总之就是把$c_ip + $formId + time() + randString(16)
改成$c_ip . $formId . time() . randString(16)
好的,我有一个函数: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(顾名思义)是一个文本字符串。由于您进行的是数学加法而不是串联,因此 $formId
和 randString(16)
中的文本字符串在从每次调用中获取不同值方面确实无济于事。由于 time()
在两个调用中相同,因此每次调用的整个计算在数学上是等效的。
通过切换到串联,$formId
和 randString(16)
都将实际发挥作用,并且 time()
相同这一事实将不成问题。每次调用 newCSRF()
都会得到不同的结果(假设 $formId
不同)。
总之就是把$c_ip + $formId + time() + randString(16)
改成$c_ip . $formId . time() . randString(16)