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

React+Django跨域请求无法设置Cookie,CSRF验证失败求助

问题排查与解决方案

核心问题分析

你遇到的CSRF cookie not set错误,根源在于跨域请求时浏览器未正确存储或发送Django设置的CSRF Cookie,或Cookie属性不符合浏览器的跨域安全要求。以下是逐步排查和修复步骤:


1. 修正Django Cookie配置

首先确保Django的CSRF和Session Cookie属性符合跨域要求,在settings.py中添加/修改以下配置:

# 强制Cookie仅通过HTTPS传输
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True

# 允许跨域发送Cookie(必须配合Secure属性)
CSRF_COOKIE_SAMESITE = 'None'
SESSION_COOKIE_SAMESITE = 'None'

这些配置会让Django自动为CSRF和Session Cookie设置正确的跨域属性,无需在视图中手动设置。


2. 简化后端视图代码

移除PublicKeyView中手动设置Cookie和CORS头的代码,因为上述配置已自动处理这些逻辑:

class PublicKeyView(View):
    def get(self, request):
        # Ensure a session ID is available
        if not request.session.session_key:
            request.session.save()

        session_id = request.session.session_key

        private_key, public_key = RSAKeyManager.get_keys(session_id)
        if not private_key or not public_key:
            # Keys are generated as bytes, so decode them before storing
            private_key, public_key = RSAKeyManager.generate_keys()
            RSAKeyManager.store_keys(session_id, private_key.decode('utf-8'), public_key.decode('utf-8'))

        if isinstance(public_key, bytes):
            public_key = public_key.decode('utf-8')

        # Retrieve CSRF token(Django会自动设置符合要求的CSRF Cookie)
        csrf_token = get_token(request)

        # Construct the JSON response
        response_data = {
            "session_id": session_id,
            "public_key": public_key,
            "csrf_token": csrf_token
        }

        # Create JsonResponse with the response data
        return JsonResponse(response_data, status=200)

移除的代码:

  • response.set_cookie('csrftoken', ...):由Django配置自动处理
  • response['Access-Control-Allow-Credentials'] = 'true':由corsheaders中间件自动处理(已设置CORS_ALLOW_CREDENTIALS = True)

3. 验证前端Cookie接收

在浏览器开发者工具中:

  1. 访问Application > Cookies > https://eliptum.tech,确认csrftoken和sessionid Cookie存在
  2. 检查get-public-key请求的响应头,确认Set-Cookie字段包含Secure; SameSite=None属性

4. 处理第三方Cookie拦截问题

如果上述步骤仍未解决问题,大概率是浏览器默认拦截了第三方Cookie(CodeSandbox属于跨域第三方站点)。此时需要调整方案:

替代方案1:传递Session ID到请求中

  • 前端从get-public-key响应中获取session_id,将其作为自定义头(如X-Session-ID)或请求参数发送到user/create接口
  • 后端修改视图,通过request.headers.get('X-Session-ID')获取Session ID,手动加载会话:
    from django.contrib.sessions.backends.db import SessionStore
    
    def create_user(request):
        session_id = request.headers.get('X-Session-ID')
        session = SessionStore(session_key=session_id)
        # 后续使用session进行操作
    

替代方案2:切换到Token认证

放弃Session Cookie,改用JWT或其他Token机制:

  • 前端获取Token后,在请求头中携带Authorization: Bearer <token>
  • 后端使用Django REST Framework的TokenAuthentication或JWT扩展处理认证

最终验证

完成上述修改后,重新测试流程:

  1. 发送get-public-key请求,确认Cookie被正确存储
  2. 发送user/create请求,检查请求头是否包含Cookie和X-CSRFToken字段
  3. 确认后端不再返回CSRF cookie not set错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 16:35:55