PHP会话令牌用于表单安全性

时间:2016-02-13 00:02:52

标签: php

我无法成功提交我在Chrome或Firefox中使用的表单。但是,该表单适用于Safari。

我上周刚开始尝试使用PHP,并在CSS Tricks上修改了这个post的代码。我试图给会话一个随机令牌,将该令牌存储在变量中,将该令牌设置为隐藏的输入字段,然后确保在提交表单时两者匹配。

问题在于,创建的会话令牌与指定为隐藏输入的值的令牌不匹配。提交表单时,会重新创建新的会话令牌,因此不会与会话中的原始随机数匹配。奇怪的是,它适用于Safari,而不适用于其他浏览器。

PHP

<?php 
session_start();

function generateFormToken($form) {

    // generate a token from an unique value, took from microtime, you can also use salt-values, other crypting methods...
    $token = md5(uniqid(microtime(), true));  

    // Write the generated token to the session variable to check it against the hidden field when the form is sent
    $_SESSION[$form.'_token'] = $token; 
    echo $token;
    return $token;
}

function verifyFormToken($form) {

    // check if a session is started and a token is transmitted, if not return an error
    if(!isset($_SESSION[$form.'_token'])) { 
        return false;
    }

    // check if the form is sent with token in it
    if(!isset($_POST['token'])) {
        return false;
    }

    // compare the tokens against each other if they are still the same
    if ($_SESSION[$form.'_token'] !== $_POST['token']) {
        return false;
    }

    return true;
}
function check_input($data)
{
    $data = trim($data);
    $data = stripslashes($data);
    $data = htmlspecialchars($data);
    return $data;
  }

if (verifyFormToken('form1')) {
    $name = check_input($_POST["name"]);
    $email = check_input($_POST["emailaddress"]);
    $message = check_input($_POST["message"]);
    $ForwardTo = 'me@gmail.com';
    $details='Name: '.$name."\n".'Email: '.$email."\n".'Message: '.$message."\n";

        //do stuff
    mail($ForwardTo,"Construction of Hope Contact",$details,"From:$email");
}

?>

相关表格:

&#13;
&#13;
<!--Markup for Contact form-->
		<form action='index.php' method='post' class='contact-format'>


		<p><input type="hidden" name="token" value="<?php echo $newToken; ?>"></p>
		<p>
      <button type="submit" name='submit' class="btn btn-primary button">Send</button>
    </p>
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:1)

我认为你所拥有的非常接近。我想我会改变一些事情,但总的来说,我认为你所拥有的是:

<强> /functions/validate.php

function fetchToken($form)
    {
        $token  =   md5(uniqid(microtime(), true));
        $_SESSION['token'][$form]   =   $token; 
        // Just return it, don't echo and return
        return $token;
    }

function matchToken($form)
    {
        if(!isset($_POST['token'][$form]))
            return false;
        // I would clear the token after matched
        if($_POST['token'][$form] === $_SESSION['token'][$form]) {
            $_SESSION['token'][$form]   =   NULL;
            return true;
        }
        // I would return false by default, not true
        return false;
    }

<强>的index.php

// Include functions
include(__DIR__.'/functions/validate.php');
// Start session
session_start();
// match the token
if(matchToken('mailer')) {
    // do stuff
    echo true;
}
?>
<form action='index.php' method='post' class='contact-format'>
    <!-- You will echo here and also set the session variable here -->
    <!-- I would also use an array to contain my tokens, cleaner I think -->
    <input type="hidden" name="token[mailer]" value="<?php echo fetchToken('mailer'); ?>">
    <button type="submit" name='submit' class="btn btn-primary button">Send</button>
</form>

答案 1 :(得分:0)

我的代码的功能似乎在Safari中很好,但其他浏览器不匹配令牌。

涉及的问题......没有图标。

post是解决问题的关键。