3

I have created a login and registration system using php. I intend to use nonces to prevent the replay attack. So far what I have is, generating a random number using (uniqid(mt_rand(),true)); and then store this on the database, and pass the same data in a hidden field to the client end, and then send it back to the server side, when the login button is clicked. if it matches the on in the database, the user is redirected to the private page, and then a new nonce is generated and updated in the database.

This is how i intend to implement it. But I'm some how not totally sure of the implementation.

4

3 回答 3

4
<?php
session_start();
//Check nonce against session
if(isset($_POST) && $_POST["nonce"] === $_SESSION["csrf"]){
    //save data
    //redirect
}
//generate new nonce for form
$_SESSION["csrf"] = uniqid(mt_rand(),true);
?>
<form method="post" action="<?php echo $_SERVER['REQUEST_URI'] ?>">
    <input type="hidden" name="nonce" value="<?php echo $_SESSION['csrf']; ?>"/>
    <!-- other form fields -->
    <!-- submit button -->
</form>
于 2013-10-24T06:47:36.947 回答
0

您可以为此目的使用 php 会话。会话是用于登录目的的更传统和有用的方法。收到表单数据后,验证该数据,然后将该数据存储在会话中即可。

于 2013-10-24T06:26:35.043 回答
0

uniqid(mt_rand(),true)不适用于 nonce 值:

http://php.net/manual/en/function.mt-rand.php

它使用具有已知特性的随机数生成器,使用 » Mersenne Twister,生成随机数的速度比 libc rand() 提供的平均速度快四倍。

http://php.net/manual/en/function.uniqid.php

他的函数不会生成加密安全值,并且不应用于加密目的。如果您需要加密安全值,请考虑改用 random_int()、random_bytes() 或 openssl_random_pseudo_bytes()。

random_bytesopenssl_random_pseudo_bytes返回不可打印的字符,但您可以将它们转换为十六进制表示:

bin2hex(random_bytes($length))

确保 nonces 缓存存储对其他用户不可用。例如,PHP 会话通常保存为 /tmp 文件夹中的文件。如果您使用的是 SESSIONS,请覆盖其默认行为:

http://php.net/manual/en/class.sessionhandlerinterface.php

无论如何,我开发并发布了一个 nonces 库:

这是您可以使用该库创建带有 nonce 的表单的方法:

<?php
require __DIR__ . '/../vendor/autoload.php';

$form = new \pedroac\nonce\Form\NonceForm(
    'token',
    new \pedroac\nonce\NoncesManager(
      new \Symfony\Component\Cache\Simple\PdoAdapter($pdo)
    )
);
if ($form->isSubmittedInvalid()) {
  /**
   * handle failure
   */
}
if ($form->isSubmittedValid()) {
  /**
   * handle the success
   */
}
?>
<form method="POST">
    <?= new HtmlNonceField($form) ?>
    <input type="submit" name="myform" value="Submit" />
</form>

你也可以这样做:

<?php
require __DIR__ . '/../vendor/autoload.php';

$manager = new \pedroac\nonce\NoncesManager(
    new \Symfony\Component\Cache\Simple\PdoAdapter($pdo)
);
$lastNonceName = $_SESSION['nonce_name'];
if(isset($_POST[$lastNonceName]) && $manager->verifyAndExpire($lastNonceName, $_POST[$lastNonceName])) {
    // handle success
}

$nonce = $manager->create();
session_start();
$_SESSION['nonce_name'] = $nonce->getName();
?>
<form method="post">
    <input type="hidden"
           name="<?= htmlspecialchars($nonce->getName()) ?>"
           value="<?= htmlspecialchars($nonce->getValue()) ?>" />
    <input type="submit" name="myform" value="Submit" />
</form>
于 2018-04-13T10:28:07.477 回答