You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React/TypeScript项目获取CSRFToken遇403错误,请求排查

React/TypeScript + Axios/Mobx 授权时CSRF Token获取失败导致403错误

我是React/TypeScript新手开发者,项目中使用Axios和Mobx实现授权功能,目前核心问题是无法获取预期的CSRFToken,请求时出现403错误(提示token不正确)。

浏览器客户端Cookie中看不到该token,但响应头里存在Cookie。后端基于Django开发,后端人员表示配置无误,我对后端代码理解有限,恳请帮忙排查问题。

相关代码

http.ts

import axios from 'axios';

export const API_URL = process.env.NEXT_PUBLIC_BASE_URL;

const $api = axios.create({
    withCredentials: true,
    baseURL: API_URL,
    xsrfHeaderName: "X-CSRFToken",
    xsrfCookieName: "csrftoken",
})

export default $api;

store.ts

export default class Store {
    async sendCode(email: string) {
        try {
            const response = await AuthService.sendCode(email);
            console.log(response);
            sessionStorage.setItem('email', response.data.email);
            this.setAuth(false);
            this.setUser(response.data.user);
        } catch (e: any) {
            console.log(e.response?.data?.message);
        }
    }

}

AuthService.ts

export default class AuthService {
    static async sendCode(email: string): Promise<AxiosResponse<AuthResponse>> {
        return $api(
            {
                method: 'post',
                url: '/auth/login/',
                data: email,
                headers: {
                    'X-CSRFToken': document.cookie.split('=')[1],
                    'X-Requested-With': 'XMLHttpRequest',
                    'Content-Type': 'application/json',
                }
            }
        )
    }
}

排查与解决方案

1. 移除手动设置的CSRF Token Header

你已经在Axios实例中配置了xsrfHeaderName和xsrfCookieName,Axios会自动从Cookie中读取csrftoken并添加到请求头X-CSRFToken中。但当前代码里手动通过document.cookie.split('=')[1]获取Token的方式非常脆弱——如果Cookie中有多个键值对,或者csrftoken不是第一个Cookie,就会拿到错误的值,直接导致403错误。

修改AuthService.ts,删除手动设置的X-CSRFToken头,并调整请求数据格式:

export default class AuthService {
    static async sendCode(email: string): Promise<AxiosResponse<AuthResponse>> {
        return $api(
            {
                method: 'post',
                url: '/auth/login/',
                data: { email }, // 改为对象格式,匹配后端JSON解析预期
                headers: {
                    'X-Requested-With': 'XMLHttpRequest',
                    'Content-Type': 'application/json',
                }
            }
        )
    }
}

2. 确认Django后端CSRF相关配置

即使后端说配置无误,仍需核对以下关键项:

  • CSRF_COOKIE_SECURE:生产环境需设为True(启用HTTPS时),开发环境可设为False
  • CSRF_COOKIE_HTTPONLY:建议设为False(虽然Axios不需要前端读取Cookie,但如果设为True,前端document.cookie确实看不到该值,但Axios仍能自动处理)
  • CSRF_TRUSTED_ORIGINS:必须包含你的前端域名(例如http://localhost:3000)
  • CORS_ALLOW_CREDENTIALS:设为True,允许跨域请求携带Cookie
  • CORS_ALLOWED_ORIGINS:包含前端域名

Django默认会在GET请求(如页面访问)时设置CSRF Cookie,但单页应用可能缺少这个触发步骤。可以在发送授权请求前,先发送一个GET请求到后端专门的CSRF端点(比如/csrf/,后端需配置该路由返回空响应并设置Cookie):

在AuthService.ts中添加获取CSRF的方法:

export default class AuthService {
    static async getCsrfToken() {
        await $api.get('/csrf/');
    }

    static async sendCode(email: string): Promise<AxiosResponse<AuthResponse>> {
        // ... 之前的修改后代码
    }
}

然后在store.ts的sendCode方法中先调用该方法:

export default class Store {
    async sendCode(email: string) {
        try {
            await AuthService.getCsrfToken(); // 先获取CSRF Cookie
            const response = await AuthService.sendCode(email);
            console.log(response);
            sessionStorage.setItem('email', response.data.email);
            this.setAuth(false);
            this.setUser(response.data.user);
        } catch (e: any) {
            console.log(e.response?.data?.message);
        }
    }
}

4. 验证Cookie是否被正确存储

修改完成后,打开浏览器开发者工具的Application > Cookies面板,确认csrftoken是否存在。如果仍然不存在,检查后端响应头中的Set-Cookie字段,看是否包含csrftoken,以及Cookie的Domain、Path等属性是否匹配前端域名。

内容的提问来源于stack exchange,提问作者shwedus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 15:17:00