Laravel 12 + Angular 20 + Sanctum SPA 集成注册功能时遭遇CSRF Token不匹配问题求助
我完全理解你连续3天卡在这里的挫败感——CSRF Token不匹配这种问题往往就是某个不起眼的小配置或代码细节没到位。咱们一步步来排查,先从代码里的明显问题入手,再核对核心配置项:
一、前端代码里的致命小错误
先看你Angular组件register()方法里的POST请求参数,这里有个低级错误:
this.http.post('http://localhost:8000/register', { username: this.username.value ?? '', email: this.username.value ?? '', // ❌ 这里写错了!应该是this.email.value password: this.password.value ?? '', password_confirmation: this.password.value ?? '' }, ...)
你把email字段的值误写成了this.username.value,这会导致后端验证失败,同时可能干扰你排查CSRF的真正问题,务必先修正这个错误。
二、CSRF Token相关核心配置核对
1. 前端Angular配置确认
你的app.config.ts里的XSRF配置是正确的:
provideHttpClient( withFetch(), withXsrfConfiguration({ cookieName: 'XSRF-TOKEN', headerName: 'X-XSRF-TOKEN' }) )
Sanctum会自动设置XSRF-TOKEN Cookie,Angular的withXsrfConfiguration会自动将该Cookie的值注入到X-XSRF-TOKEN请求头中,配合你设置的withCredentials: true,能确保Cookie在跨域请求中正常传递。
小优化:POST请求里手动添加的'Accept': 'application/json'头可以去掉,Angular的HttpClient默认会发送该头。
2. 后端Laravel配置修复
(1)Sanctum 状态域配置
你的.env里SANCTUM_STATEFUL_DOMAINS被注释了:
# SANCTUM_STATEFUL_DOMAINS=localhost:4200,localhost:8000,localhost:3000
虽然sanctum.php默认配置包含localhost:4200,但建议取消注释并明确设置,避免环境变量优先级歧义:
SANCTUM_STATEFUL_DOMAINS=localhost:4200,localhost:8000
(2)Session 配置
.env里SESSION_DOMAIN保持为空即可(本地开发无需设置),SESSION_SAME_SITE=lax和SESSION_SECURE_COOKIE=false都符合本地HTTP开发的需求,无需调整。
(3)CORS 配置
你的cors.php配置完全正确:
paths包含sanctum/csrf-cookie和register,确保跨域路由被允许allowed_origins包含http://localhost:4200supports_credentials=true(关键配置,必须开启才能传递Cookie)
三、额外排查点
清除浏览器缓存与Cookie:残留的旧CSRF Cookie可能导致不匹配。打开浏览器开发者工具(Application面板),删除
XSRF-TOKEN和laravel_sessionCookie后重新测试。检查请求头是否携带X-XSRF-TOKEN:在浏览器Network面板查看
/register请求的Request Headers,确认存在X-XSRF-TOKEN头,且其值与XSRF-TOKENCookie一致。如果缺失,可尝试手动添加头:
// 在POST请求的headers中手动注入 headers: { 'X-XSRF-TOKEN': document.cookie.split('; ').find(row => row.startsWith('XSRF-TOKEN='))?.split('=')[1] ?? '' }
- 查看Laravel日志:打开
storage/logs/laravel.log,查看具体的CSRF错误详情(比如Token为空还是不匹配),这能快速定位问题根源。
四、修复后的前端register函数示例
修正email字段后的代码:
register(): void { this.http.get('http://localhost:8000/sanctum/csrf-cookie', { withCredentials: true }) .subscribe(() => { this.http.post('http://localhost:8000/register', { username: this.username.value ?? '', email: this.email.value ?? '', // 已修正 password: this.password.value ?? '', password_confirmation: this.password.value ?? '' }, { withCredentials: true }) .subscribe({ next: (res) => { console.log('Registrierung erfolgreich', res); }, error: (err) => { console.error('Registrierung fehlgeschlagen: ', err); console.error('Laravel Fehlerdetails: ', err.error); // 打印Laravel返回的具体错误 } }); }); }
先按上述步骤修正,清除Cookie后测试,应该能解决CSRF Token不匹配的问题!
内容来源于stack exchange

