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

Django 5与Nuxt3跨域请求Cookie无法携带问题求助

解决Django 5 + Nuxt 3跨域Cookie无法携带问题

问题核心

跨域场景下,后端登录接口返回的sessionid和csrftoken已在响应头的Set-Cookie中,但前端后续请求未携带任何Cookie,Postman测试正常但前端失效,本质是后端Cookie配置与前端请求规则不匹配。


后端Django配置修正

1. 统一Cookie跨域规则

浏览器强制要求:当SameSite=None时,Cookie必须设置Secure=True(仅HTTPS传输),之前的SESSION_COOKIE_SECURE=False是错误配置,会被浏览器拦截。同时需同步CSRF Cookie的配置:

# settings.py
CORS_ALLOWED_ORIGINS = ['http://localhost:3000']  # 仅允许前端域名,移除重复的CORS_ORIGIN_WHITELIST
CORS_ALLOW_CREDENTIALS = True

# Session Cookie配置
SESSION_COOKIE_SAMESITE = 'None'
SESSION_COOKIE_SECURE = True  # 必须与SameSite=None配合
SESSION_COOKIE_HTTPONLY = True  # 保持开启,防止XSS

# CSRF Cookie配置(需与Session Cookie对齐)
CSRF_COOKIE_SAMESITE = 'None'
CSRF_COOKIE_SECURE = True
CSRF_COOKIE_HTTPONLY = False  # 设为False,让前端能读取CSRF Token

# 允许前端携带CSRF请求头
CORS_ALLOW_HEADERS = [
    'Accept',
    'Accept-Encoding',
    'Authorization',
    'Content-Type',
    'Cookie',
    'X-CSRFToken',  # 新增,用于前端传递CSRF Token
]

2. 简化登录视图逻辑

无需手动返回sessionid,Django会自动设置Session Cookie,手动返回反而可能干扰前端逻辑:

@action(detail=False, methods=['POST'])
def login(self, request):
    username = request.data['username']
    password = request.data['password']
    user = authenticate(request, username=username, password=password)
    
    if user is not None:
        login(request, user)
        return Response({'message': "Logged in!"})
    else:
        return Response(
            {'message': "Invalid credentials provided"},
            status=status.HTTP_400_BAD_REQUEST
        )

前端Nuxt 3请求配置

1. 强制携带凭证

所有跨域请求必须设置credentials: 'include',否则浏览器不会携带Cookie:

2. 自动携带CSRF Token

前端需从Cookie中读取csrftoken,并放到X-CSRFToken请求头中,供Django验证。可以封装统一的请求工具:

// composables/useApi.js
export const useApi = () => {
  // 从Cookie中提取CSRF Token
  const getCsrfToken = () => {
    const cookieList = document.cookie.split('; ')
    const csrfItem = cookieList.find(item => item.startsWith('csrftoken='))
    return csrfItem ? csrfItem.split('=')[1] : ''
  }

  // 封装带认证的请求
  const fetchWithAuth = async (url, options = {}) => {
    const defaultOptions = {
      credentials: 'include',  // 关键:跨域携带Cookie
      headers: {
        'Content-Type': 'application/json',
        'X-CSRFToken': getCsrfToken(),  // 自动带上CSRF Token
        ...options.headers
      },
      ...options
    }
    return await $fetch(url, defaultOptions)
  }

  return { fetchWithAuth }
}

3. 登录请求示例

// 页面组件中使用
const { fetchWithAuth } = useApi()

const handleLogin = async () => {
  try {
    const res = await fetchWithAuth('/api/login/', {
      method: 'POST',
      body: JSON.stringify({ username: 'yourname', password: 'yourpwd' })
    })
    console.log(res.message)
  } catch (err) {
    console.error(err.response._data.message)
  }
}

本地开发适配

如果本地不想用HTTPS,可以临时调整Cookie规则(仅开发环境使用,生产必须用HTTPS):

# settings.py 仅开发环境
SESSION_COOKIE_SAMESITE = 'Lax'
SESSION_COOKIE_SECURE = False
CSRF_COOKIE_SAMESITE = 'Lax'
CSRF_COOKIE_SECURE = False

同时确保前后端域名完全一致:比如后端用localhost:8000,前端必须用localhost:3000,不能混用localhost和127.0.0.1(浏览器视为不同域名)。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 08:16:09