【问题标题】:Ajax error 403 Forbidden CodeIgniterAjax 错误 403 禁止 CodeIgniter
【发布时间】:2017-03-23 09:28:02
【问题描述】:

我的 html 页面上有两个链接:

<a id="1" onclick="like(this.id)">first</a>
<a id="2" onclick="like(this.id)">Second</a>

我的 JS 如下:

function like (id) {
    $.ajax({
        type:'POST',
        data: {
            func:
                'getNewLocations',
            '<?php echo $this->security->get_csrf_token_name(); ?>':
                '<?php echo $this->security->get_csrf_hash(); ?>',
            message:id
        },
        url:'<?php echo base_url();?>index.php/Category/like',
        success: function(result, statut) {
            if (result == 'add') {
                //do something
            }
            else if (result == 'remove') {
                //do something
            }
        }
    });
}

而php方法如下(仅举例):

public function like() {
    echo 'add';
}

当我首先单击链接 1 时,ajax 请求工作正常,服务器回答“添加”。但是当我点击链接 2 时,出现 403 错误。更令人惊讶的是,当我点击链接 2 上的第一个按钮时,它可以工作,但链接 1 却没有。 我使用 codeIgniter。

知道为什么以及如何解决它吗? 谢谢

【问题讨论】:

  • 在函数event.preventDefault();在这行function like (id) {之后添加这个
  • 我没有看到您返回新的 csrf 令牌名称/值以在下一个服务器请求中使用,因此您的后续请求被拒绝
  • 它不会改变任何东西..
  • @PatrickEvans 我该怎么做?
  • @devpro,如果锚标签实际上没有 href 属性,则不需要。当没有 href 属性时,它不会在点击时执行导航操作

标签: javascript php ajax codeigniter


【解决方案1】:

由于您似乎使用 CSRF 令牌来验证请求,因此任何发送无效令牌的请求都将被拒绝。

当您第一次单击任一锚点时,您会用完该令牌。因此,为了发出额外的请求,您需要在响应中取回一个新令牌并使用它来代替旧令牌。

您只需发送回您的数据值,在这种情况下为 "add",以及您的 csrf 值:get_csrf_token_name()get_csrf_hash()

您可以发回包含这些值的 JSON 值,而不是只发回纯文本,例如

php 脚本

function like(){
   $output = new stdClass;
   $output->csrfName = $this->security->get_csrf_token_name();
   $output->csrfHash = $this->security->get_csrf_hash();
   $output->data = "add";
   echo json_encode($output);
}

在 JavaScript 中

//Initial csrf values
var csrfName = '<?php echo $this->security->get_csrf_token_name();?>';
var csrfHash = '<?php echo $this->security->get_csrf_hash();?>';
function like (id) {
    //create data object here so we can dynamically set new csrfName/Hash
    var data = {
       func:'getNewLocations',
       message:id
    };
    data[csrfName] = csrfHash;

    $.ajax({
        type:'POST',
        data: data, 
        //dataType tells jQuery to expect JSON response
        dataType:"json",
        url:'<?php echo base_url();?>index.php/Category/like',
        success: function(result, statut) {
            if(result.csrfName){
               //assign the new csrfName/Hash
               csrfName = result.csrfName;
               csrfHash = result.csrfHash;
            }
            if (result.data == 'add') {
                //do something
            }
            else if (result.data == 'remove') {
                //do something
            }
        }
    });
}

请注意,如果您支持支持 ECMAScript 2015 的浏览器,您可以使用 computed keys 在数据对象初始化程序中设置您的 csrf 值

    $.ajax({
        type:'POST',
        data: {
            [csrfName]:csrfHash,
            func:'getNewLocations',
            message:id
        }, 

【讨论】:

  • 我按照你说的做了,但我的第一次点击仍然有效,但第二次点击无效,同样的错误 403
  • @LucasPierrat,您确定您正确实施了吗?您是否已验证是否正在接收新令牌,然后随每个新请求一起发送出去?您是否检查过您的服务器日志以查看它们是否记录了 403 的原因?
【解决方案2】:

第一次提交后csrf令牌不再有效,你有两种选择。

您可以在 config.php 中设置以下内容

$config['csrf_regenerate'] = FALSE;

或更新页面上的 csrf 令牌。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-05
    • 2018-10-23
    • 1970-01-01
    • 2017-03-12
    • 2018-08-12
    • 2018-11-03
    • 2020-12-12
    • 1970-01-01
    相关资源
    最近更新 更多