Django REST Framework与React跨域会话失效及购物车会话方案咨询
你的问题核心是跨域请求的Cookie同源策略限制:浏览器默认不会在跨域Ajax请求中携带Cookie,所以后端设置的会话ID Cookie无法被前端请求带上,导致后端每次都认为是新会话,自然读不到之前设置的会话数据(触发KeyError)。要实现购物车的会话功能,需要从Django后端配置、前端Axios配置两方面入手解决。
1. 配置Django跨域支持(使用django-cors-headers)
首先安装并配置Django的跨域处理库,这是前后端分离项目的必备配置:
步骤1:安装依赖
pip install django-cors-headers
步骤2:修改Django配置文件(settings.py)
在INSTALLED_APPS中添加corsheaders:
INSTALLED_APPS = [ # ...其他已有的App 'corsheaders', 'rest_framework', ]
在MIDDLEWARE中添加跨域中间件(注意要放在CommonMiddleware之前):
MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', # ...其他中间件 ]
添加跨域允许的源和凭证设置:
# 允许前端的域名/端口,本地开发就是你的React地址 CORS_ALLOWED_ORIGINS = [ "http://127.0.0.1:3000", # 生产环境添加实际的前端域名,比如"https://your-frontend-domain.com" ] # 允许跨域请求携带Cookie(必须开启) CORS_ALLOW_CREDENTIALS = True
2. 调整Django会话Cookie的配置
为了让会话Cookie能跨域传递,需要修改settings.py中的会话相关参数:
# 本地开发环境可以设为None,生产环境如果前后端共享主域名,比如都是xxx.com下的子域名,可以设为".xxx.com" SESSION_COOKIE_DOMAIN = None # 允许跨域Cookie,开发环境可以设为"Lax",如果是跨域且使用HTTPS的生产环境,建议设为"None" SESSION_COOKIE_SAMESITE = "Lax" # 本地开发用HTTP,所以设为False;生产环境用HTTPS的话要设为True SESSION_COOKIE_SECURE = False # 确保Cookie可以被JavaScript访问(如果需要前端读取Cookie的话,不过购物车场景后端处理会话,这个可选) SESSION_COOKIE_HTTPONLY = False
注意:如果设置
SESSION_COOKIE_SAMESITE = "None",必须同时开启SESSION_COOKIE_SECURE = True,否则浏览器会拒绝保存Cookie(这是浏览器的安全规范)。本地开发如果用HTTP的话,可能需要临时调整浏览器的安全设置来测试,或者使用HTTPS的本地服务。
3. 配置前端Axios请求携带Cookie
在React项目中,确保Axios发起请求时携带Cookie,需要全局配置或者单个请求设置withCredentials: true:
全局配置(推荐)
在你的Axios初始化文件(比如src/utils/axios.js)中添加:
import axios from 'axios'; const instance = axios.create({ baseURL: 'http://127.0.0.1:8000', // 后端API地址 withCredentials: true, // 关键:允许携带Cookie }); export default instance;
之后所有用这个实例发起的请求都会自动携带Cookie。
单个请求配置
如果不想全局配置,也可以在单个请求中设置:
axios.post('/api/cart/add/1/true/2/', {}, { withCredentials: true, }) .then(response => { console.log(response.data); }) .catch(error => { console.error(error); });
4. 测试验证
完成以上配置后,按照你的测试用例验证:
- 用浏览器访问
http://127.0.0.1:8000/create/,后端设置会话request.session['one']。 - 用React前端调用
cart_add视图,此时请求会携带会话Cookie,后端可以读取到已有的会话数据,也能新增会话内容。 - 再访问
http://127.0.0.1:8000/read/,或者前端调用read接口,应该能正常打印会话中的one值,不会触发KeyError。
额外注意事项
- 生产环境部署时,务必使用HTTPS,并且调整
SESSION_COOKIE_SECURE = True、SESSION_COOKIE_SAMESITE = "None"(如果前后端域名不同)。 - 如果前后端部署在同一个主域名的不同子域名下,比如后端是
api.yourshop.com,前端是www.yourshop.com,可以设置SESSION_COOKIE_DOMAIN = ".yourshop.com",这样Cookie可以在子域之间共享。
内容的提问来源于stack exchange,提问作者Rik Schoonbeek

