Express集成csurf传CSRF token仍报invalid csrf token如何解决
问题根因
ForbiddenError: invalid csrf token报错来自两个明确的配置问题,Postman测试正常是因为Postman会自动关联携带cookie,且手动构造请求时参数位置正确,前端代码问题点:
- Axios
post方法传参错误:该方法的参数顺序为post(请求地址, 请求体数据, 请求配置对象),你的代码把headers、data打包为一个对象作为第二个参数传入,整个对象会被当成请求体发送给后端,你之前在默认请求头中配置的X-CSRF-Token根本没有被放到请求头里,后端拿不到校验token。 - 跨域场景未开启凭证携带:csurf的cookie校验模式依赖浏览器自动携带服务端种下的
_csrfcookie做秘钥比对,前后端不同源时,Axios默认不会主动携带cookie,后端拿不到校验秘钥,就算请求头带了token也会校验失败。
修复步骤
按顺序修改对应配置即可解决:
- 修正登录接口的POST传参,把请求配置移到第三个参数位置:
const handelLogin = (e) => { e.preventDefault(); // 参数顺序:接口地址 -> 请求体 -> 请求配置 API.post('/auth/login', { email, password }, { headers: { 'Content-Type': 'application/json' } } ).then(({ data }) => { if (data.token) { localStorage.setItem('token', data.token); window.location.href = '/admin' } }).catch((e) => { console.log(e) }) }
- 初始化Axios实例时开启跨域携带cookie配置:
// 初始化你的API实例时添加withCredentials字段 const API = axios.create({ baseURL: '替换为实际后端服务地址', withCredentials: true // 跨域请求自动关联携带对应域名下的cookie })
- 后端Express配置跨域规则时,允许凭证携带,注意跨域源不能用通配符
*:
const cors = require('cors') app.use(cors({ origin: '替换为实际前端访问地址,本地开发一般是http://localhost:5173这类地址', credentials: true // 允许跨域请求携带cookie }))
补充:你当前csurf配置默认读取的CSRF请求头就是
X-CSRF-Token,和前端设置的头字段匹配,这部分无需调整。如果要做体验优化,可以加一层Axios响应拦截器,遇到CSRF校验失败的403响应时,自动重新拉取新的CSRF token并重试原请求,避免1小时token过期后用户需要手动刷新页面。
内容的提问来源于stack exchange,提问作者Sarkaw Salar
相关产品推荐
相关产品推荐

