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

Django Auth提示CSRF Cookie未设置,Next.js登录请求报错求助

问题分析与解决方案

核心问题根源

你遇到的"CSRF cookie not set"错误,本质是跨域请求时未正确携带CSRF cookie,同时Django的CSRF验证要求两个条件:请求头带X-CSRFToken,且请求中包含CSRF cookie,二者缺一不可。你的代码存在两个关键疏漏:

  1. 跨域请求未开启withCredentials,导致浏览器不会向Django发送CSRF cookie
  2. 未确保浏览器在发送POST请求前已获取到CSRF cookie

分步解决方案

第一步:配置Django后端(必须)

  1. 安装并配置django-cors-headers以支持跨域带凭证请求

    pip install django-cors-headers
    
  2. 修改settings.py:

    INSTALLED_APPS = [
        # 其他已安装应用
        'corsheaders',
    ]
    
    MIDDLEWARE = [
        'corsheaders.middleware.CorsMiddleware',
        'django.middleware.common.CommonMiddleware',
        # 确保CsrfViewMiddleware在中间件列表中
        'django.middleware.csrf.CsrfViewMiddleware',
        # 其他中间件
    ]
    
    # 允许跨域带凭证
    CORS_ALLOW_CREDENTIALS = True
    # 信任你的Next.js域名
    CORS_ORIGIN_WHITELIST = ['http://localhost:3000']
    # 允许该域名的CSRF请求
    CSRF_TRUSTED_ORIGINS = ['http://localhost:3000']
    
  3. 新增获取CSRF cookie的视图(确保浏览器能拿到cookie)
    在views.py中添加:

    from django.http import JsonResponse
    from django.middleware.csrf import get_token
    
    def get_csrf_token(request):
        return JsonResponse({'csrfToken': get_token(request)})
    

    在urls.py中配置路由:

    from django.urls import path
    from .views import get_csrf_token
    
    urlpatterns = [
        # 其他路由
        path('api/get-csrf-token/', get_csrf_token, name='get_csrf_token'),
    ]
    

第二步:修改前端Login函数

修改后的代码解决了跨域带凭证、提前获取CSRF cookie的问题:

export const login = (username, email, password) => async dispatch => {

    function getCookie(name) {
        let cookieValue = null;
        if (document.cookie && document.cookie !== '') {
            const cookies = document.cookie.split(';');
            for (let i = 0; i < cookies.length; i++) {
                const cookie = cookies[i].trim();
                if (cookie.substring(0, name.length + 1) === (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }

    // 提前发送GET请求获取CSRF cookie
    await axios.get('http://localhost:8000/api/get-csrf-token/', { withCredentials: true });
    
    const csrftoken = getCookie('csrftoken');

    console.log(csrftoken);

    const config = {
        headers: {
            'Content-Type': 'application/json',
        },
        withCredentials: true // 跨域请求携带cookie
    };

    const config_two = {
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json',
            'X-CSRFToken': csrftoken,
        },
        withCredentials: true // 必须开启,否则浏览器不发送CSRF cookie
    };

    console.log(config_two)

    const body = JSON.stringify({ email, password });
    const body_two = JSON.stringify({ username, password });

    try {
        const res = await axios.post(`http://localhost:8000/auth/jwt/create/`, body, config);
        const res_two = await axios.post(`http://localhost:8000/api-token-auth/`, body_two, config_two);
        
        dispatch({
            type: LOGIN_SUCCESS,
            payload: res.data
        });

        dispatch(load_user());
        toast.success("You are logged in");
    } catch (err) {
        // 打印具体错误信息便于排查
        console.error(err.response?.data || err.message);
        toast.error("Something went wrong");
        dispatch({
            type: LOGIN_FAIL
        })
    }
};

可选优化:全局配置Axios

避免每个请求都重复设置withCredentials,可以全局配置Axios:

// 在utils/axios.js中创建实例
import axios from 'axios';

const axiosInstance = axios.create({
    withCredentials: true,
});

export default axiosInstance;

之后在login函数中用axiosInstance代替原生axios即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 22:41:23