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接收
在浏览器开发者工具中:
- 访问
Application > Cookies > https://eliptum.tech,确认csrftoken和sessionidCookie存在 - 检查
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扩展处理认证
最终验证
完成上述修改后,重新测试流程:
- 发送
get-public-key请求,确认Cookie被正确存储 - 发送
user/create请求,检查请求头是否包含Cookie和X-CSRFToken字段 - 确认后端不再返回
CSRF cookie not set错误
内容的提问来源于stack exchange,提问作者Gabi
相关产品推荐
相关产品推荐

