本地不同端口跨域登录:SANCTUM_STATEFUL_DOMAINS配置疑问
Laravel Sanctum跨域登录CORS问题解决
问题场景
React SPA运行在127.0.0.1:8000,Laravel后端运行在127.0.0.1:3000,使用Axios发起登录请求时,Chrome控制台抛出CORS错误:
Access to XMLHttpRequest at 'http://localhost:8000/login' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
已尝试的配置
- 在
sanctum.php中扩展了stateful域名列表:
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf( '%s%s', 'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,localhost:8000,127.0.0.1:3000,::1', Sanctum::currentApplicationUrlWithPort() ))),
- 在
.env中先后尝试设置:SANCTUM_STATEFUL_DOMAINS=127.0.0.1:3000SANCTUM_STATEFUL_DOMAINS=127.0.0.1:8000
- Axios请求代码:
const config={ headers:{ accept:'application/json', referer:'127.0.0.1:8000/', 'Access-Control-Allow-Origin':'*' } } function fetchCookie(){ const response = axios.get('http://localhost:8000/sanctum/csrf-cookie') const response1 = axios.post('http://localhost:8000/login',loginData,config) console.log(response1); }
正确配置方案
1. 修正.env配置
打开项目根目录的.env文件,修改以下两项:
# 前端SPA的域名+端口(React运行在8000,所以填此值) SANCTUM_STATEFUL_DOMAINS=127.0.0.1:8000 # Cookie的domain,不要加端口,统一用本地IP SESSION_DOMAIN=127.0.0.1
修改后执行配置缓存刷新:
php artisan config:clear
2. 调整config/cors.php配置
确保跨域配置覆盖登录接口,同时限制合法来源:
return [ 'paths' => ['api/*', 'sanctum/csrf-cookie', 'login'], 'allowed_methods' => ['*'], // 精确指定前端origin,比*更安全 'allowed_origins' => ['http://127.0.0.1:8000'], 'allowed_origins_patterns' => [], 'allowed_headers' => ['*'], 'exposed_headers' => [], 'max_age' => 0, 'supports_credentials' => true, // 必须设为true,因为要传递Cookie ];
补充说明:把login加入paths是合理操作,登录接口确实需要跨域访问,比通配*的安全性更高。
3. 修复Axios请求代码
- 移除前端请求中的
Access-Control-Allow-Origin头,这个头由后端返回给浏览器,前端设置无效 - 修正
referer为完整URL(带http协议) - 确保请求异步执行,获取CSRF Cookie和登录请求有依赖顺序,必须等Cookie拿到后再发登录请求,同时修正后端地址(之前写反了端口):
const config={ headers:{ accept:'application/json', referer:'http://127.0.0.1:8000/' } } async function fetchCookie(){ // 先等待CSRF Cookie获取完成 await axios.get('http://127.0.0.1:3000/sanctum/csrf-cookie') // 再发起登录请求(后端运行在3000端口) const response1 = await axios.post('http://127.0.0.1:3000/login', loginData, config) console.log(response1); }
内容的提问来源于stack exchange,提问作者Yurei
相关产品推荐
相关产品推荐

