Next.js无法接收Django返回的Cookie问题求助
核心原因
跨域请求中,前端fetch默认不处理Cookie,同时Django的CORS配置不符合带Cookie的跨域要求。
解决方案步骤
1. 修改Next.js的fetch请求配置
在登录请求中添加credentials: "include",并指定Content-Type头(匹配JSON格式的请求体):
async function logIn(e: FormEvent) { e.preventDefault(); const body = JSON.stringify({ email: email, password: password }); const res = await fetch(process.env.API_URL + "login/", { method: "POST", body: body, credentials: "include", // 关键:允许跨域接收Cookie headers: { "Content-Type": "application/json", // 明确告诉后端请求体格式 }, }); if (res.status === 200) { router.push("/"); } }
2. 修正Django后端的CORS配置与Cookie设置
关键修改点:
- 不能使用
Access-Control-Allow-Origin: *,必须指定具体前端域名(如http://localhost:3000) - 添加
Access-Control-Allow-Credentials: true头,允许跨域携带Cookie - 密码验证必须用Django内置的
check_password方法(直接比较明文密码极度不安全) - 调整
SameSite属性为Lax(Strict会在跨域跳转时阻止Cookie发送)
修改后的Django视图代码:
import json from django.http import JsonResponse from django.contrib.auth.models import User from django.views.decorators.csrf import csrf_exempt @csrf_exempt def login(req): # 处理OPTIONS预检请求(跨域请求会先发送OPTIONS) if req.method == "OPTIONS": res = JsonResponse({}) res["Access-Control-Allow-Origin"] = "http://localhost:3000" res["Access-Control-Allow-Credentials"] = "true" res["Access-Control-Allow-Methods"] = "POST, OPTIONS" res["Access-Control-Allow-Headers"] = "Content-Type" return res body = json.loads(req.body.decode("utf-8")) res = None if User.objects.filter(email=body["email"]).exists(): user = User.objects.get(email=body["email"]) # 使用Django内置方法验证哈希密码(Django默认存储哈希后的密码) if user.check_password(body["password"]): res = JsonResponse({"success": True}) res.set_cookie( "AuthToken", json.dumps({"id": user.id}), max_age=60 * 60 * 24, httponly=False, samesite="Lax", secure=False, # 生产环境HTTPS下改为True ) else: res = JsonResponse({"success": False}, status=401) else: res = JsonResponse({"success": False}, status=404) res["Access-Control-Allow-Origin"] = "http://localhost:3000" res["Access-Control-Allow-Credentials"] = "true" print(res.cookies) return res
3. 推荐优化:使用django-cors-headers管理CORS
手动设置CORS头容易遗漏预检请求,推荐使用官方维护的django-cors-headers库:
- 安装:
pip install django-cors-headers - 在
settings.py中配置:
INSTALLED_APPS = [ # ... 'corsheaders', ] MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', # 放在中间件列表最前面 'django.middleware.common.CommonMiddleware', # ... ] CORS_ALLOWED_ORIGINS = [ "http://localhost:3000", # 替换为你的前端实际域名/端口 ] CORS_ALLOW_CREDENTIALS = True
额外注意事项
- 永远不要直接存储或比较明文密码,Django默认对密码进行哈希处理,必须用
check_password验证 - 生产环境中,Cookie的
secure属性要设为True(仅通过HTTPS传输),httponly建议设为True(防止XSS攻击窃取Cookie) - 测试时确保前端和后端的域名、端口完全匹配,避免跨域配置不匹配
内容的提问来源于stack exchange,提问作者TheStupid
相关产品推荐
相关产品推荐

