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

如何在CodeIgniter 4中确保所有AJAX请求持续验证CSRF Token

解决CodeIgniter中AJAX登录请求CSRF验证403错误

问题原因分析

  1. URL不匹配:表单action使用validate_login(下划线命名),但AJAX请求URL为validate-login(中划线命名),若CSRFStrict配置为true,URI不匹配会直接触发CSRF验证失败。
  2. 重复生成Token导致不一致:Controller中使用csrf_hash()会强制生成新Token,与CodeIgniter自动 regenerate的Token冲突,导致前端发送的Token与服务器Session中存储的Token不匹配。
  3. 验证失败时未正确设置状态:原Controller中字段验证失败时,未将success设为0,可能导致前端逻辑异常。

解决方案

步骤1:统一AJAX请求URL

将AJAX请求URL改为与表单action一致的下划线命名:

$("#form").validate({
    // ... 原有规则与提示
    submitHandler : function(form,e){
        e.preventDefault(); 
        var form_data = new FormData(form);
        $.ajax({
            url  : SITE_URL+"validate_login", // 统一为下划线命名
            type : "POST",
            contentType: false,
            cache: false,
            processData:false,
            data : form_data,
            success : function(response){
                $('.txt_csrfname').val(response.data.token);
                if(response.success == "1"){
                    $("#alert-message").css("display","none");  
                    window.location.href= SITE_URL+"Dashboard";                      
                }else{
                    console.log(response.data.token);
                    $("#alert-message").css("display","");
                }
            },
            error : function(){
                $("#alert-message").css("display","");
                $("#alert-message .alert").html("<strong>Error!</strong> Request failed.");
            }
        });
    }
});

步骤2:修改Controller获取Token的方式

使用getCSRFHash()获取当前Session中的Token,避免手动重复生成:

public function validate_login(){
 $request = service('request');
 $requestArr = $request->getPost();
 $responseArr = array("success"=>"1","data"=>array(),"message"=>"");
 $data = array();
 // 获取当前Session中的CSRF Token,而非强制生成新Token
 $data['token'] = $request->getCSRFHash();
 $ipaddress = $this->request->getIPAddress();


 $rules = [
     'username' => 'required|valid_email',
     'password' => 'required'
 ];

if($this->validate($rules)){
     $userArr = $this->Auth->login($requestArr['username']);    
     if(!empty($userArr)) {
         $verify_password = password_verify($requestArr['password'],$userArr->password);
         if($verify_password){
             $responseArr['success'] = "1"; 
             $responseArr['message'] = "Loged in successfully.";

             $this->session->set([                        
                 'tbl_users_id'=>$userArr->tbl_users_id,
                 'full_name'=>$userArr->full_name,
                 'username'=>$userArr->username,
                 'email'=>$userArr->email
             ]);

             $logArr = array(
                 'user_id' => $userArr->tbl_users_id,
                 'module' => $this->module,
                 'module_id' => $userArr->tbl_users_id,
                 'action' => "LOGIN",
                 'ip_address' => $ipaddress,
                 'remarks' => "User Loged In",
                 'raw_data'=> ""
             );

             insert_log($logArr);
         }else{
             $responseArr['success'] = "0";
             $responseArr['message'] = "In-valid username or password.";
         }
     }else{
         $responseArr['success'] = "0";
         $responseArr['message'] = "In-valid username or password.";
     }   
 }else{
     $responseArr['success'] = "0"; // 补充设置失败状态
     $responseArr['message']= "Required Fields are missing";
 }

 $responseArr['data']= $data;
 output($responseArr);
}

步骤3:可选 - 同步更新Token名称(若配置动态变更)

如果你的CSRF Token名称不是固定值,可在Controller中返回名称,前端同步更新input的name属性:

// Controller中添加返回Token名称
$data['token_name'] = $request->getCSRFTokenName();
// JS中更新name属性
success : function(response){
    $('.txt_csrfname').attr('name', response.data.token_name);
    $('.txt_csrfname').val(response.data.token);
    // ... 原有逻辑
}

验证要点

  1. 确保请求URI与生成Token时的URI完全一致(包括大小写、符号),尤其是CSRFStrict设为true时。
  2. 每次提交FormData时,都会重新从表单获取最新的Token值,无需额外处理。

内容的提问来源于stack exchange,提问作者Snehalkumar Vasava

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 02:59:57