根本原因是浏览器SameSite策略升级:Chrome 80+默认将未声明SameSite的Cookie视为Lax,跨域请求下Lax阻止发送;SameSite=None必须配合Secure=true(HTTPS),且XSRF-TOKEN和session cookie均需显式设置。
为什么 Laravel 的跨域 Cookie 总是丢失
根本原因不是 Laravel 配置错了,而是浏览器对 SameSite 属性的强制策略升级 —— Chrome 80+ 默认把未声明 SameSite 的 Cookie 当作 SameSite=Lax,而跨域请求(比如前端在 http://localhost:3000 调用 https://api.example.com)下,Lax 会直接阻止 Cookie 发送。即使你开了 withCredentials: true,后端也设置了 Access-Control-Allow-Credentials: true,Cookie 还是不带。
Laravel 中间件里怎么正确设置 SameSite=None
不能只改 config/session.php 里的 'same_site' => 'none' —— 这只影响 session cookie,且 Laravel 7+ 才支持该配置项;更重要的是:Chrome 要求 SameSite=None 必须配合 Secure=true(即只在 HTTPS 下发送),否则直接忽略该设置,降级为 Lax。
-
config/session.php中必须同时设:"secure" => env('SESSION_SECURE_COOKIE', true),
"same_site" => 'none' - 开发环境(HTTP)无法真正使用
SameSite=None,浏览器会拒绝;本地调试建议用ngrok或localhost(Chrome 对localhost有例外,允许SameSite=None+Secure=false,但仅限开发) - 若需动态判断环境,可在中间件中手动覆盖响应头:
return $next($request)->withCookie(cookie('XSRF-TOKEN')
->sameSite('None')
->secure(true));
跨域场景下 XSRF-TOKEN 和 session cookie 都要处理
很多人只改了 session cookie,却忽略了 Laravel 默认通过 XSRF-TOKEN Cookie + X-XSRF-TOKEN 请求头做 CSRF 防护。这个 Token 也是 Cookie,同样受 SameSite 限制。