You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CodeIgniter AJAX表单提交中CSRF令牌再生问题排查

CodeIgniter AJAX表单重复提交CSRF 403错误解决方法

问题背景

开发CodeIgniter应用时,已开启$config['csrf_regenerate'] = TRUE;的CSRF防护,但AJAX表单重复提交时频繁出现403错误。当前做法是在页面加载时通过<?= $this->security->get_csrf_hash(); ?>获取令牌并随表单发送,但重复提交时令牌不匹配导致验证失败。

问题根源

开启csrf_regenerate = TRUE后,服务器会在每次有效请求后生成新的CSRF令牌并更新对应Cookie。但当前前端代码是在页面加载时一次性获取令牌,后续提交仍使用这个旧值,第二次提交时服务器已生成新令牌,自然出现验证不匹配的403错误。

最佳处理方案

1. 动态从Cookie获取最新令牌

CodeIgniter会将有效CSRF令牌存储在Cookie中(对应配置项$config['csrf_cookie_name']),每次请求后自动更新。前端可以通过读取Cookie实时获取最新令牌,避免依赖页面加载时的静态值。

2. 修改AJAX提交逻辑

提交表单时,实时从Cookie提取当前有效的CSRF哈希值,替代原本静态获取的旧值。

(可选)控制器主动返回新令牌

如果需要更主动地同步前端令牌,可以在控制器响应中返回新生成的CSRF信息,前端更新本地存储的令牌值。


修改后的代码示例

优化后的jQuery代码

$(document).ready(function() {
    // 从Cookie中获取指定名称的值
    function getCookie(name) {
        let value = "; " + document.cookie;
        let parts = value.split("; " + name + "=");
        if (parts.length === 2) return parts.pop().split(";").shift();
    }

    $("#add_category_form").on("submit", function(e) {
        e.preventDefault();

        const csrfTokenName = '<?= $this->security->get_csrf_token_name(); ?>';
        // 动态读取Cookie中的最新CSRF哈希
        const csrfHash = getCookie('<?= $this->config->item('csrf_cookie_name'); ?>');

        const formData = $(this).serialize() + "&" + csrfTokenName + "=" + csrfHash;

        $.post("<?= base_url('CategoriesController/process_add_category'); ?>", formData, function(response) {
                console.log(response);
            })
            .fail(function(jqXHR, textStatus, errorThrown) {
                console.error("AJAX错误:", textStatus, errorThrown);
            });

        return false;
    });
});

(可选)控制器返回新令牌的实现

public function process_add_category() {
    $categoryName = $this->input->post("category_name");
    
    // 返回包含新CSRF信息的JSON响应
    echo json_encode([
        'status' => 'success',
        'data' => $categoryName,
        'csrf_token_name' => $this->security->get_csrf_token_name(),
        'csrf_hash' => $this->security->get_csrf_hash()
    ]);
}

对应前端成功回调更新令牌:

$.post("<?= base_url('CategoriesController/process_add_category'); ?>", formData, function(response) {
        const res = JSON.parse(response);
        console.log(res.data);
        // 存储新令牌,供下次提交使用
        window.currentCsrfHash = res.csrf_hash;
    })

注意事项

  • 确认config.php中$config['csrf_cookie_name']与$config['csrf_token_name']配置正确(默认分别为csrf_cookie_name和csrf_test_name)。
  • 避免在表单中手动添加CSRF隐藏字段(除非每次提交前动态更新),防止与Cookie中读取的令牌冲突。
  • csrf_regenerate = TRUE能提升安全性,但必须保证前端每次提交都使用最新令牌,否则必然触发403错误。

内容的提问来源于stack exchange,提问作者Adrian Gaile Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 06:25:07