为什么Jquery Ajax在Codeigniter3.0.0中启用csrf_protection会得到403(禁止)错误? [英] Why Jquery Ajax get 403 (forbidden) errors with csrf_protection enable in Codeigniter3.0.0?

查看:67
本文介绍了为什么Jquery Ajax在Codeigniter3.0.0中启用csrf_protection会得到403(禁止)错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用jquery和CodeIgniter3.0.0开发注册 但是当我将csrf_protection设置为true后,我的ajax将停止工作.但是,如果将csrf_protection设置为False,我的ajax将可以正常工作.

I'm developing a registration using jquery and CodeIgniter3.0.0 But after I enable csrf_protection to true my ajax is stop working.But if I disable csrf_protection to False my ajax will work perfect.

这是我的表格

<?PHP echo form_open('account#', array('method' => 'POST', 'id' => 'createform')); ?>
<div class="control-group">
    <label class="control-label"  for="lname">Last Name</label>
    <div class="control">
        <?PHP echo form_input('lastname', set_value('lastname', ''), 'id="lastname" class="form-control ln-error" ') ?>
    </div>
</div>
<div class="control-group">
    <label class="control-label"  for="fname">First Name</label>
    <div class="control">
        <?PHP echo form_input('firstname', set_value('firstname', ''), 'id="firstname" class="form-control ln-error" ') ?>
    </div>
</div>
<div class="control-group">
    <label class="control-label"  for="email"> Email <span id="email-error">Email is existed</span></label>
    <div class="control">
        <?PHP echo form_input('email', set_value('email', ''), 'id="email" class="form-control ln-error" placeholder="Example@website.com" ') ?>
    </div>
</div>
<div class="control-group">
    <label class="control-label" >Password</label>
    <div class="control">
        <?PHP echo form_password('pass', set_value('pass', ''), 'id="pass" class="form-control ln-error" ') ?>
    </div>
</div>
<div class="control-group">
    <div class="controls">
        <?PHP echo form_submit('csubmit', "Create Account", 'id="csubmit" class="btn btn-success btn-lg" ') ?>
    </div>
</div>                                    
<?PHP echo form_close(); ?>

完成表单后,我使用了Jquery来验证表单字段

After I finish form I used Jquery to validate form field

<strip>
 $(document).already(function(){
       $("#email").keyup(function () {
            if ($("#email").val().length >= 0 || $("#email").val() !== '') {
                ajax_call();
            }
        });

 });

function ajax_call() {
        $.ajax({
            type: "post",
            url: "<?php echo base_url('account/check_user_existing'); ?>",
//            data: $("#createform").serialize(),
            data: {
                '<?php echo $this->security->get_csrf_token_name(); ?>': '<?php echo $this->security->get_csrf_hash(); ?>',
                 email:$("#email").val()
    },
            success: function () {
                alert("success");
            },
            dataType: "text",
            cache: false,
            success: function (respond) {
                if ($.trim(respond) === "true") {
                    $("#email-error").css({'display': 'inline', 'font-size': '12px'});
                    $(".form-error").css({'border': '1px solid red', 'background-color': 'rgba(255, 0, 0, 0.17)', 'color': 'black'});
                    document.getElementById("csubmit").disabled = true;
                } else {
                    $("#email-error").css({'display': 'none'});
                    $(".form-error").css({'border': '', 'background-color': '', 'color': ''});
                    document.getElementById("csubmit").disabled = false;
                }
            }
        });
    }
</strip>

在我通过单击表单元素进行验证之后,我将得到如下图所示的错误

And after I validation by click on the form element I will get error as below image

推荐答案

在设置好代码以使其发挥作用之后,我发现CSRF令牌正在每个AJAX调用上重新生成(更改).

After setting up your code to have a play with, I discovered that the CSRF Token is being regenerated (changed ) on each AJAX Call.

因此,第一次按键很好-后续按键会导致帖子被拒绝,因为您的CSRF令牌不再有效.

So the first keypress is fine - subsequent ones result in the post being rejected as your CSRF Token is no longer valid.

快速讨厌的问题:您可以做的一件事就是更改

Quick Nasty Fix: One thing you can do is change

//$config['csrf_regenerate'] = TRUE;
$config['csrf_regenerate'] = FALSE;

理想情况下,您可以将其设置为TRUE,然后在每个帖子回复中将新的令牌发送回去.我正在努力.

Ideally you could leave it set to TRUE and on each post response send back the new Token. I'm working on that.

CSRF Regenerate = true修正:

处理您要通过设置

$config['csrf_regenerate'] = TRUE;

您可以执行此操作... 注意:我在其中有一些console.log调试代码-您可以将其删除.

you can do this... NOTE: I have some console.log debug code in this - you can remove it.

<script>    
function ajax_call() {
            var tokenValue = $("input[name='csrf_test_name']");
            console.log('Token is ' + tokenValue.val());
            $.ajax({
                type: "post",
                url: "<?php echo base_url('account/check_user_existing'); ?>",
                data: {
                    '<?php echo $this->security->get_csrf_token_name(); ?>': tokenValue.val(),
                    email:$("#email").val()
                },
                dataType: "json",
                cache: false,
                success: function (data) {
                    console.log('The returned DATA is ' + JSON.stringify(data));
                    console.log('The returned token is ' + data.token);
                    tokenValue.val(data.token);

                    if (data.response == false) {
                        $("#email-error").css({'display': 'inline', 'font-size': '12px'});
                        $(".form-error").css({'border': '1px solid red', 'background-color': 'rgba(255, 0, 0, 0.17)', 'color': 'black'});
                        document.getElementById("csubmit").disabled = true;
                    } else {
                        $("#email-error").css({'display': 'none'});
                        $(".form-error").css({'border': '', 'background-color': '', 'color': ''});
                        document.getElementById("csubmit").disabled = false;
                    }
                }
            });
        }
</script>

注意:dataType从文本更改为json.另外,我已经硬编码了令牌名称,这是不希望的.可以通过多种方式来传递(适合您的练习).

Note: The dataType is changed from text to json. Also I have hardcoded the token name which isn't desirable. That can be passed in, in a number of ways ( an exercise for you ).

以及 account/check_user_existing

    public function check_user_existing(){
            $new_token = $this->security->get_csrf_hash();
            $response = FALSE;
            if($this->input->post('email') == 'testmy@email.address')
            {
                $response = TRUE;
            }
            echo json_encode(array('response'=>$response,'token'=>$new_token));
            exit();
     }

为了在每个Keyup事件上的每个帖子上重新生成CSRF令牌,可能会有些落伍.但这是另一个问题.

For the sake of regenerating the CSRF Token on each Post on every Keyup event might be a little overboard. But that's another issue.

这篇关于为什么Jquery Ajax在Codeigniter3.0.0中启用csrf_protection会得到403(禁止)错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆