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

跨域下React通过Axios请求Laravel API报CSRF令牌不匹配错误

Laravel Sanctum 前后端分离登录跨域报错修复

你碰到的ERR_NETWORK无状态码错误,本质是跨域携带Cookie场景下CORS配置不符合浏览器规范,和Sanctum的EnsureFrontendRequestsAreStateful中间件直接相关:当请求开启withCredentials: true要跨域带Cookie时,浏览器强制要求后端不能用通配符*匹配允许源,否则直接拦截响应,前端拿不到任何有效状态码。


第一步:修正CORS配置违规项

你当前config/cors.php里allowed_origins设为['*']是核心错误,凭证模式下通配符源直接违反CORS规范,必须明确填写前端的实际访问地址,同时补全Cookie相关的响应头暴露配置,修改后内容如下:

'paths' => ['*'],
'allowed_methods' => ['*'],
// 禁止用*!明确写前端实际访问地址,本地React默认跑3000端口就填对应地址,生产环境替换为线上前端域名
'allowed_origins' => ['http://localhost:3000', 'https://你的前端线上域名'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
// 必须暴露XSRF相关响应头,否则前端无法读取写入的Cookie
'exposed_headers' => ['XSRF-TOKEN', 'laravel_session'],
'max_age' => 0,
'supports_credentials' => true,

改完配置务必执行php artisan config:clear清除配置缓存,否则修改不会生效。

第二步:对齐Sanctum和Session配置

打开config/sanctum.php找到stateful配置项,把前端访问域名加进去,这个配置的作用是告诉Sanctum哪些来源的请求需要走Cookie+CSRF的有状态鉴权,不要把后端API域名本身加入列表:

'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
    '%s%s',
    'localhost,localhost:3000,127.0.0.1,127.0.0.1:3000,你的前端线上域名',
    env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : ''
))),

同时检查.env文件的几个关键配置:

  • SESSION_DOMAIN:本地开发前后端都用localhost不同端口时,设为.localhost(前面带点,兼容同域下不同端口);生产环境前后端为同根域不同子域时设为.你的根域名.com,完全跨域本地测试可先留空
  • SANCTUM_STATEFUL_DOMAINS:和上面sanctum配置的域名对应,本地环境填localhost:3000即可
  • SESSION_SECURE_COOKIE:本地用http访问时设为false,生产https环境设为true

第三步:统一Axios请求配置

你当前代码只在登录post请求里加了withCredentials: true,但前面获取csrf-cookie的get请求没加这个配置,会导致XSRF-TOKEN Cookie无法正常写入浏览器。建议直接设置Axios全局默认配置,不用每个请求单独传参:

// 在Axios初始化位置添加全局配置
axios.defaults.withCredentials = true;
axios.defaults.baseURL = 'http://localhost:8000'; // 后端API根地址
axios.defaults.headers.common['Accept'] = 'application/json';
axios.defaults.headers.common['Content-Type'] = 'application/json';
// Axios默认的xsrf配置本身就是正确的,无需额外修改:默认读XSRF-TOKEN Cookie,自动放到X-XSRF-TOKEN请求头

// 登录方法可简化为
async function submitForm(e) {
  e.preventDefault();
  const body = { email, password };
  // 全局已开withCredentials,请求会自动携带、写入Cookie
  await axios.get('/sanctum/csrf-cookie');
  const res = await axios.post('/api/login', body);
  console.log(res);
}

相关现象说明

  • 禁用EnsureFrontendRequestsAreStateful中间件后请求正常,是因为这个中间件关闭后,Sanctum不再要求SPA请求走Cookie+CSRF校验,请求退化为无状态模式,不会触发浏览器的跨域凭证校验逻辑,但会丢失Sanctum自带的SPA安全鉴权能力,生产环境不建议这么做
  • 移除withCredentials: true后返回419 CSRF不匹配,是因为跨域请求不带凭证时,浏览器不会存储、回传Cookie,后端拿不到前端的XSRF-TOKEN,自然校验失败

补充踩坑点

  • Laravel 9+版本要确认app/Http/Kernel.php的api中间件组里,EnsureFrontendRequestsAreStateful放在SubstituteBindings前面,中间件顺序错误也会触发异常
  • 本地开发不要混用127.0.0.1和localhost访问前后端,二者虽然指向本地但属于不同源,会导致Cookie无法跨端口共享,统一用同一种域名访问即可
  • 改完配置记得重启Laravel服务,同时清除浏览器下localhost相关的旧Cookie缓存,避免历史脏数据干扰

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 00:18:26