Vue3+Quasar SPA对接Laravel API遇CSRF令牌不匹配(419错误)
问题:Laravel Sanctum + Axios 自动携带XSRF-TOKEN失败导致419错误
环境与问题
- Vue3 + Quasar SPA部署在
localhost:8080,Laravel API部署在localhost:80(Docker容器运行) - 页面刷新时已调用
/sanctum/csrf-cookie,浏览器Cookie中已存在XSRF-TOKEN - 调用
/login接口时返回419状态码,手动添加X-XSRF-TOKEN请求头后请求成功,但Axios未自动完成该过程
现有配置
Quasar/Vue Axios全局配置
axios.defaults.withCredentials = true; axios.defaults.baseURL = 'http://localhost/' axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'
Laravel .env配置
... APP_URL=http://localhost ... SESSION_DRIVER=cookie SESSION_DOMAIN=localhost SANCTUM_STATEFUL_DOMAINS=localhost:8080
Laravel cors.php配置
'paths' => ['api/*', 'sanctum/csrf-cookie', 'login'], 'allowed_methods' => ['*'], 'allowed_origins' => ['*'], 'allowed_origins_patterns' => [], 'allowed_headers' => ['*'], 'exposed_headers' => [], 'max_age' => 0, 'supports_credentials' => true,
Laravel Kernel.php配置
'api' => [ EnsureFrontendRequestsAreStateful::class, ThrottleRequests::class . ':api', SubstituteBindings::class, ],
/login请求的Cookie头信息
Cookie: XSRF-TOKEN=eyJpdiI6InJ0SXhRZDVEL21JaEUvL0ptTGdmUlE9PSIsInZhbHVlIjoiU28zenNEQ1VOYTR3NXRVd1JtcU1RaUsvK1BCTHpNUGtUZ3c3T3I0d3lKQjhlZzNjMkVIeDBoOFZWanJDVkw2cWc0RGRDM0NWako0cnN1RXdveThwZkE4dW51aS9Ia1FYVXVsSlpqdW9CK1F3amJTMlFITzhpSCtudDYvY2VpUnUiLCJtYWMiOiIyODkyMzhjYjU5YzMzODY2YTkxZTY3M2MzOWZkNDkwMGQyYjBjNDg0ZTgwMzM3ZDc5NjYwYTcyNWFmZTUyZjExIiwidGFnIjoiIn0%3D; laravel_session=eyJpdiI6IlQxYXZ4WGhYZGZ5Lzk2WlF5QzJRUHc9PSIsInZhbHVlIjoidE5QQUpaeFh3WWg4cjFJNG82SXNDY1FGUmplWFN5cG5na08zazRmbXFJRFhJVWdUZS81UzJ1RWNaaC84VWxxcTFPdWNuTXd5K0pDaW0zTDliME5BSHl2ZGw4M01lbk1EUDl6SnlVWWFLM2lxNHBTOFBmei9QQXhMaTZLazJSeEEiLCJtYWMiOiIwNjFlNTFkNzIzZTIyZDhjYTg0MmVhMGViMGZjYTU4MmZjY2VmOGMyOWRjODgyNGY3NmE3NjExZDIyYWVhMDU1IiwidGFnIjoiIn0%3D; 3mcV2b1Mp2zT3MoKAWWTOeGlp0TkNFu9FneRzMLK=eyJpdiI6InY1cUYwaXhjdnZlQVRiNDNqaFRMMEE9PSIsInZhbHVlIjoiaE52dVg0dnRYdmE2dDVUT0lUUkJWeXAyaXNkaXMvZkw3RjJwT0hrbkdybUx4K0JyZ2RZV2lMYjEvT3F2TUEvOWQzejkxN05SaHlZMVliUktmUnhVRkwwYTB4cDYzUVB5VFA3MnA5SmlhMmc1Y0VSY3NyMm1JVnd2Vk1XZmFlWU05dEZJWVQrSjFqQ2h6aktFemdFVWZ6cjJBM2MydHNIMlcxRSsvWk1xaDU0Y1RDcHBFUndOL2ZlMXBVWVhyUEQrNS8vOTI5Qmx0TmpMQUtZQ0sxUHZLMEd5MnpGdC91SnVDeDJ5RkF4Tkc0dUphNHhLRFQwUE5Vc0hlR29JaVZqQ3p4Yi9wTFpMUE42UmJOWXoxN0V2bGZlZHduTVRmZUdkcHVnLzBkOWQ0emQyajhjelptSG9XUzRDb3lmZVlpMk5OK1p0R2R2eTdET2FjcTVhVGR4WmRtNVd4ekQ4SHZaeEg3cTUxY0Y2ZVhFdWhJeDh1SUkreUkwdFBmMjErUmdGIiwibWFjIjoiYWVmY2NkY2NiZmJiY2ZhNjkyMTVhODE2MTg0MjkxNTYxZWQ0N2I4NzMyY2RjOWE2NDdiNGY4NjljYjk5NDY0YyIsInRhZyI6IiJ9
补充发现
Axios自动携带了包含XSRF-TOKEN的Cookie头,但未自动生成X-XSRF-TOKEN请求头。手动添加该头后请求成功,手动实现代码如下:
const login = async () => { let cookies; await axios.get("/sanctum/csrf-cookie").then((response) => { const { get } = useCookies(['XSRF-TOKEN']); cookies = get('XSRF-TOKEN'); }); axios.defaults.headers['X-XSRF-TOKEN'] = cookies; await axios.post("/login", form).then((response) => { console.log(response) }); }
解决方案
要实现Axios自动处理X-XSRF-TOKEN头,需完成以下配置:
- 显式配置Axios的XSRF参数
Axios默认会读取XSRF-TOKENCookie并生成X-XSRF-TOKEN请求头,但显式配置可避免隐式匹配问题,将以下代码加入Axios全局配置:
axios.defaults.xsrfCookieName = 'XSRF-TOKEN'; // 与Laravel设置的Cookie名一致 axios.defaults.xsrfHeaderName = 'X-XSRF-TOKEN'; // 与Laravel期望的请求头名一致
- 简化登录请求逻辑
调用/sanctum/csrf-cookie后,直接发送登录请求即可,Axios会自动携带所需头:
const login = async () => { await axios.get('/sanctum/csrf-cookie'); const response = await axios.post('/login', form); console.log(response); }
- Docker环境校验
确保Docker容器端口映射正确(宿主机80端口映射到容器80),容器内APP_URL和SESSION_DOMAIN配置与宿主机一致,避免Cookie作用域不匹配。
验证方法
发送请求前打开浏览器开发者工具Network面板,查看/login请求的Request Headers中是否包含X-XSRF-TOKEN头,且值与Cookie中的XSRF-TOKEN一致(Axios会自动解码Cookie中的URL编码值)。
内容的提问来源于stack exchange,提问作者j_gomes
相关产品推荐
相关产品推荐

