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

Next.js调用Django用户资料更新接口时出现CSRF cookie未设置的403错误

Next.js调用Django用户资料更新接口时出现CSRF cookie未设置的403错误

看起来你遇到了跨站请求伪造(CSRF)的典型问题,结合你贴的代码,我帮你梳理下可能的原因和修复方案:

一、Next.js端请求的Cookie头格式错误

你在updateprofile/route.ts里构造Cookie头的方式有问题,只传递了sessionid的值,没有遵循键=值的Cookie格式,也没把csrftoken正确加入Cookie头。另外,fetch请求需要明确配置凭证传递规则,让浏览器正确处理会话Cookie。

修改你的POST函数:

export async function POST(req: NextRequest) { // App Router推荐用NextRequest类型
    console.log('i am reaching here')
    const cookieStore = cookies()

    const csrfToken = cookieStore.get('csrftoken')
    const sessionid = cookieStore.get('sessionid')

    // 先检查必要Cookie是否存在,避免索引报错
    if (!csrfToken || !sessionid) {
        return Response.json({ message: '缺少CSRF或会话Cookie' }, { status: 400 })
    }

    console.log('CSRF Token:', csrfToken.value)
    console.log('sessionid:', sessionid.value)

    // 解析请求体,App Router的req.body是流类型
    const requestBody = await req.json()

    const profileUpdateResponse = await fetch(`${API_URL}/update-profile/`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'X-CSRFToken': csrfToken.value,
            // 正确构造Cookie头:多个Cookie用分号分隔
            'Cookie': `sessionid=${sessionid.value}; csrftoken=${csrfToken.value}`
        },
        credentials: 'include', // 强制携带凭证,确保会话一致性
        body: JSON.stringify(requestBody)
    })

    // 兼容不同类型的响应内容
    const responseData = await profileUpdateResponse.json().catch(() => profileUpdateResponse.text())

    if (profileUpdateResponse.status === 403) {
        return Response.json({ message: 'CSRF验证失败' }, { status: 403 })
    }

    if (profileUpdateResponse.status === 401) {
        return Response.json({ message: '未授权,请重新登录' }, { status: 401 })
    }

    return Response.json(responseData, { status: profileUpdateResponse.status })
}

Django的CSRF Token是通过Set-Cookie头返回的,你需要先发送一个GET请求到Django的接口(比如获取用户信息的接口),让浏览器接收并存储CSRF Cookie,之后再发起POST更新请求。如果直接调用更新接口,浏览器还没有CSRF Cookie,就会触发403错误。

三、Django视图的小问题修复

你的update_profile视图在GET请求分支里没有定义user变量,会导致报错,需要把用户实例的获取移到函数开头:

@login_required
def update_profile(request):
    user = request.user  # 移到这里,确保GET/POST请求都能拿到当前用户
    if request.method == 'POST':
        # 原POST逻辑保持不变
    else:
        # 返回当前用户数据
        return JsonResponse({
            'user': {
                'username': user.username,
                'email': user.email,
                # 根据需要添加其他字段
            }
        })

四、Django设置的确认

你当前的settings.py配置大部分是正确的,再核对几个关键项:

  • CORS_ALLOW_CREDENTIALS = True:必须开启,允许跨域请求携带凭证
  • CSRF_COOKIE_HTTPONLY = False:允许前端读取CSRF Cookie(你已经设置)
  • CORS_ALLOWED_ORIGINS包含http://localhost:3000(你已经添加)
  • CORS_ALLOW_HEADERS包含x-csrftoken(你已经加入)

如果还是有问题,可以尝试:

  • 清除浏览器缓存和Cookie,重新测试
  • 在Django视图里打印request.META.get('HTTP_X_CSRFTOKEN'),确认是否接收到了CSRF Token
  • 查看浏览器Network面板,检查请求头里的X-CSRFToken和Cookie是否正确发送

备注:内容来源于stack exchange,提问作者lorentz kalume

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 17:57:58