Django+ReactJS中HttpOnly CSRF Cookie获取异常问题咨询
问题现象
我正在开发一款Web应用,后端基于Django部署在xxx.xxx.xxx.xxx:8000,前端基于ReactJS部署在xxx.xxx.xxx.xxx:3000,已在后端配置CORS策略仅允许前端发起请求。出现两个反常现象:
- 后端返回的CSRF Cookie带有
HttpOnly标记,按规则JavaScript不应能提取该Cookie,但ReactJS应用却可以实现提取; - 移除
HttpOnly标记后,反而无法设置或获取该Cookie。
Django CORS配置
# CSRF Cookie Settings CSRF_COOKIE_AGE: Optional[int] = None CSRF_TRUSTED_ORIGINS = [ 'http://localhost:3000', 'http://xxxx.xxxx.xxxx.xxxx:3000' ] CSRF_COOKIE_HTTPONLY = True # CORS(cross origin resource sharing) settings CORS_ORIGIN_ALLOW_ALL = False CORS_ALLOW_CREDENTIALS = True CORS_ALLOWED_ORIGINS = [ 'http://localhost:3000', 'http://xxxx.xxxx.xxxx.xxxx:3000', ] CORS_ALLOW_METHODS = [ 'DELETE', 'GET', 'PATCH', 'POST', 'PUT', ]
ReactJS请求代码
fetch("http://xxxx.xxxx.xxxx.xxxx:8000/get_csrf",{ method: 'GET', mode: 'cors', credentials:'same-origin', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' } }) .then(response => { console.log(...response.headers) response.json() }) .then( (result) => { console.log(this.getCookie('csrftoken')) }, (error) => { } )
问题原因解答
1. HttpOnly标记时能提取的假象
你看到的“提取成功”并非真的读取了后端返回的HttpOnlyCookie,而是浏览器同源Cookie混淆导致的:
- 若开发时曾直接访问
localhost:8000(Django后端域名),浏览器会留存不带HttpOnly标记的csrftoken(Django默认在同源请求下,早期版本不会强制添加HttpOnly); - React请求中
credentials:'same-origin'配置错误:当前后端域名/端口不同时,该配置会阻止浏览器发送跨域Cookie,此时你获取到的csrftoken是前端所在域名(xxx.xxx.xxx.xxx:3000)下的旧Cookie,而非后端返回的HttpOnlyCookie。实际上,HttpOnlyCookie永远无法被JavaScript读取。
2. 移除HttpOnly后无法获取的核心原因
问题出在credentials配置:
- 当后端移除
HttpOnly标记后,JS本应能读取Cookie,但credentials:'same-origin'会让浏览器在跨域请求中不携带、也不保存后端返回的Cookie; - 正确配置应为
credentials:'include',这样浏览器才会在跨域请求中携带Cookie,并保存后端返回的Cookie,此时JS才能读取非HttpOnly的csrftoken。
验证建议
- 清空浏览器所有Cookie后重新测试,会发现
HttpOnly标记的Cookie根本无法被this.getCookie读取; - 将React请求中的
credentials改为'include',同时移除后端CSRF_COOKIE_HTTPONLY = True配置,此时能正常获取到Cookie。
内容的提问来源于stack exchange,提问作者nikita_trifan
相关产品推荐
相关产品推荐

