使用ajax提交表单时,CSRF令牌无效

时间:2017-04-17 11:57:34

标签: php ajax

我有一个简单的CSRF预防令牌,在不使用AJAX提交时可以正常工作。但是当使用AJAX时,它会一直显示我创建的自定义错误。

这是我生成令牌的功能:

function make_form_token() {
    $token = base64_encode(openssl_random_pseudo_bytes(32));
    $_SESSION['token'] = $token;
    return $token;
} // end CSRF token generation

然后在名为form_token

的隐藏字段中调用该函数
<form id="contact-form" method="post">
    <input type="hidden" name="form_token" value="<?php echo make_form_token(); ?>">

    <div class="col-sm-5 col-md-4 col-xs-6">
        <button id="send" type="submit" name="submit" class="btn btn--primary type--uppercase">Send Enquiry</button>
    </div>
</form>

然后ajax从contact-submit.php

调用php脚本
$(document).ready(function(){
    $( "#send" ).click(function(){
        $( "#send" ).prop( "disabled", true );
        $( ".hideloader" ).show();
        $( "#send" ).html( "Sending <img src='img/ajax-loader.gif'>" );

        var form_data = $( "#contact-form" ).serialize();

        $.ajax({
            type: 'POST',
            url: 'contact-submit.php',
            data: form_data
        }).done(function(response) {
            $( "#server-results" ).hide().html(response).fadeIn("slow");
            $( "#send" ).prop("disabled", false);
            $( "#send" ).html( "Send Enquiry" );
        });
    });
});

接触submit.php

if ($_SERVER["REQUEST_METHOD"] == "POST") {

    $message = "";

    if (!isset($_SESSION['token']) || $_POST['form_token'] !== $_SESSION['token']) {
        $message .= "There was an error submitting the form. Please try again later. <br/>";
    }

    if ($message) {
        echo "<div class='red-error'><b>There were errors in your form:</b> <br/>" . $message . "</div>";
    } else {    
        // send email etc. 
    }
}

1 个答案:

答案 0 :(得分:0)

我想我知道你的问题是什么。如果我错了,请告诉我。你有这个HTML:

<form id="contact-form" method="post">
<input type="hidden" name="form_token" value="<?php echo make_form_token(); ?>">
<div class="col-sm-5 col-md-4 col-xs-6">
<button id="send" type="submit" name="submit" class="btn btn--primary type--uppercase">Send Enquiry</button>
</div>
</form>

在页面加载时生成了这个HTML,但我认为这也是在POST上生成的,因此当您将form与有效form_token一起发送并且请求到达服务器时,它会生成一个新的令牌(生成HTML时),将其存储到$ _SESSION中,这与它在页面加载时生成的不同。当且仅当您的请求是GET时,解决方案是生成form

编辑:确保在POST请求到达服务器时启动会话。

EDIT2:您可以通过以下方式检查您的请求是否为POST:

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
     // The request is using the POST method
}