简体   繁体   English

如何在使用php的登录系统中使用nonce以避免重放攻击?

[英]How to use nonce in a login system using php to avoid replay attack?

I have created a login and registration system using php. 我已经使用php创建了一个登录和注册系统。 I intend to use nonces to prevent the replay attack. 我打算用nonce来防止重放攻击。 So far what I have is, generating a random number using (uniqid(mt_rand(),true)); 到目前为止我所拥有的是,使用(uniqid(mt_rand(),true));生成一个随机数(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. 如果它与数据库中的on匹配,则将用户重定向到私有页面,然后在数据库中生成并更新新的nonce。

This is how i intend to implement it. 这就是我打算如何实现它。 But I'm some how not totally sure of the implementation. 但我有些不确定实施方式。

<?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>

you can use php sessions for this purpose. 你可以使用PHP会话来达到这个目的。 Session is a more conventional and useful approach for login purposes. 会话是一种更常规和有用的登录方法。 After recieving form data validate that data and then storing that data in session will work. 收到表单数据后验证数据然后将该数据存储在会话中将起作用。

uniqid(mt_rand(),true) is not appropriate for a nonce value: uniqid(mt_rand(),true)不适用于nonce值:

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

It uses a random number generator with known characteristics using the » Mersenne Twister, which will produce random numbers four times faster than what the average libc rand() provides. 它使用具有已知特征的随机数发生器,使用»Mersenne Twister,它将产生比平均libc rand()提供的速度快四倍的随机数。

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

his function does not generate cryptographically secure values, and should not be used for cryptographic purposes. 他的函数不会生成加密安全值,也不应用于加密目的。 If you need a cryptographically secure value, consider using random_int(), random_bytes(), or openssl_random_pseudo_bytes() instead. 如果需要加密安全值,请考虑使用random_int(),random_bytes()或openssl_random_pseudo_bytes()。

random_bytes and openssl_random_pseudo_bytes return characters that are not printable, but you can convert them to hexadecimal representations: random_bytesopenssl_random_pseudo_bytes返回不可打印的字符,但您可以将它们转换为十六进制表示形式:

bin2hex(random_bytes($length))

Make sure the nonces cache storage is not available to other users. 确保其他用户无法使用nonce缓存存储。 For instance, PHP sessions are usually saved as files inside the /tmp folder. 例如,PHP会话通常保存为/ tmp文件夹中的文件。 If you're using SESSIONS, override their default behaviour: 如果您正在使用SESSIONS,请覆盖其默认行为:

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

Anyway, I developed and released a nonces library: 无论如何,我开发并发布了一个nonces库:

This is how you could create a form with a nonce using the library: 这是您使用库创建带有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>

You could also do it like this: 你也可以这样做:

<?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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM