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 }) }
二、确保请求更新接口前已获取CSRF Cookie
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
相关产品推荐
相关产品推荐

