如何在Next.js中为Django设置CSRF Cookie解决403错误
Next.js调用Django接口时CSRF 403错误的解决方法
问题描述
我是Next.js新手,正在给Django应用开发前端,当前调用Django接口的route.js代码如下:
import { NextResponse } from 'next/server'; import axios from 'axios'; //import { cookies } from 'next/headers'; export async function POST(req: Request) { const { imageData } = req.body; try { // Django backend const response = await axios.post( 'http://localhost:8000/souci/capture/', { imageData } ); return NextResponse.json({response}); } catch (error) { console.error('Error sending image data to Django:', error); return NextResponse.json({ success: false, error: 'Failed to send image data to Django' }); } } export async function GET(req: Request) { // return }
Django控制台抛出403错误:
WARNING:django.security.csrf:Forbidden (CSRF cookie not set.): /souci/capture/ [20/Feb/2024 04:55:44] "POST /souci/capture/ HTTP/1.1" 403 2870
我尝试过两种方法但未解决:
- 设置axios默认值:
axios.defaults.xsrfCookieName = 'csrftoken' axios.defaults.xsrfHeaderName = "X-CSRFTOKEN"
- 创建固定值cookie(不确定如何关联到POST请求):
cookies().set('csrftoken', 'souci', { maxAge: 60 * 60 * 24, // 一天(秒) httpOnly: true, // 禁止客户端访问 sameSite: 'strict', });
需要解决如何在POST函数中正确配置CSRF Token的问题。
解决方案
1. 从Django获取合法CSRF Token并携带请求
不能手动设置固定CSRF Token,必须从Django获取有效Token,再携带到POST请求中:
import { NextResponse } from 'next/server'; import axios from 'axios'; import { cookies } from 'next/headers'; export async function POST(req: Request) { // 注意:必须await解析请求体 const { imageData } = await req.json(); try { // 第一步:请求Django的CSRF端点获取Token const csrfRes = await axios.get('http://localhost:8000/csrf/', { withCredentials: true, // 必须开启,才能接收并保存Django的CSRF Cookie }); // 从响应头的Set-Cookie中提取csrftoken const csrfToken = csrfRes.headers['set-cookie']?.split('csrftoken=')[1]?.split(';')[0]; // 第二步:携带CSRF Token发送POST请求 const response = await axios.post( 'http://localhost:8000/souci/capture/', { imageData }, { headers: { 'X-CSRFTOKEN': csrfToken, // 将Token放入请求头 }, withCredentials: true, // 保持会话Cookie传递 } ); return NextResponse.json(response.data); } catch (error) { console.error('Error sending image data to Django:', error); return NextResponse.json({ success: false, error: 'Failed to send image data to Django' }); } }
2. 配置Django允许跨域请求
因为本地开发时Next.js(通常3000端口)和Django(8000端口)属于跨域,需在Django中配置CORS:
- 安装依赖:
pip install django-cors-headers
- 修改
settings.py:
INSTALLED_APPS = [ # 原有应用 'corsheaders', # 添加这一行 ] MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', # 必须放在CommonMiddleware之前 'django.middleware.common.CommonMiddleware', # 原有中间件 ] # 允许Next.js的本地地址 CORS_ALLOWED_ORIGINS = [ "http://localhost:3000", ] # 允许携带Cookie(关键,否则CSRF Token无法传递) CORS_ALLOW_CREDENTIALS = True
3. 关键注意点
- 禁止手动设置固定CSRF Token:Django的CSRF Token是动态生成的,固定值会被判定为非法。
- 必须开启
withCredentials: true:axios请求中开启此选项才能在请求间传递Cookie。 - 正确解析请求体:Next.js API路由中,
req.body需要用await req.json()解析,直接解构会得到undefined。
内容的提问来源于stack exchange,提问作者Oneiros
相关产品推荐
相关产品推荐

