CSRF与Cookie

【背景知识】

Cookie分为2种:

临时cookie,没有expire-day,浏览器打开网页得到,关闭网页销毁。

本地cookie,有expire-day,浏览器打开网页得到,生命期结束后才销毁,不论网页是否关闭。


浏览器同时打开了A页面和B页面(二者不同域名),A页面中有B页面的资源C。

所以用户打开A页面时,会请求B页面中的资源C,发给B的数据包中就带有临时cookie,有些浏览器甚至包括本地cookie,比如FF2,FF3,Opera,Chrome,Android等。


【攻击原理】

1. 假设A也是恶意网站,A构造对资源C的请求时可以是一次恶意操作。

2. 用户访问B时已经得到了授权Cookie。

3. 用户访问A,就被发送了一次恶意操作。因为用户在访问B时携带了Cookie,被浏览器认为是正常授权操作,导致用户被执行了A的恶意操作。

这便是CSRF。


【注意】

其中Cookie作为凭证并不是必须的,那样CSRF执行起来更简单了,都不需要上述的第2步骤。


【防护】

1. Referer检测,如果Referer来自于A,B检测Referer不是B则判定为CSRF。

2. 加Token,用户先访问B得到一个隐藏在表单中的Token,用户执行操作时,会在在参数中携带Token。B检测Token有误则判定为CSRF。


<think>好的,用户现在遇到了“CSRF cookie not set”的问题,需要我的帮助。首先,我需要回想一下之前用户询问过关于微信小程序适配Django CSRF的问题,可能他现在在实施过程中遇到了这个错误。 首先,用户可能按照之前的解决方案配置了Django小程序,但实际请求时还是触发了这个错误。我需要分析可能的原因。常见的导致“CSRF cookie not set”的原因有哪些呢? 1. **CSRF中间件未启用**:Django的CSRF保护依赖于中间件,如果用户没有正确配置,或者中间件被注释掉了,就会导致这个问题。 2. **Cookie未正确传递**:微信小程序默认不携带Cookie,需要手动设置`withCredentials`为true,或者在请求头中正确包含Cookie信息。 3. **未获取CSRF Token**:用户可能没有在首次请求时获取CSRF Token,或者在后续请求中没有正确携带Token。 4. **域名未配置**:微信小程序要求请求的域名必须加入白名单,如果未配置,可能导致请求被拦截,无法获取Cookie。 5. **HTTPS问题**:Django可能配置了CSRF_COOKIE_SECURE为True,但小程序在测试环境使用HTTP,导致Cookie无法写入。 6. **路径问题**:CSRF Cookie的路径请求的接口路径不匹配,导致浏览器或小程序无法正确发送Cookie。 接下来,我需要根据这些可能的原因,逐步给出解决方案。同时,考虑到用户之前的问题是关于微信小程序的适配,我需要特别强调小程序特有的注意事项,比如`withCredentials`的设置、域名白名单等。 可能需要分步骤指导用户检查中间件配置、确保Cookie被正确携带、检查域名白名单、处理HTTPS问题等。另外,用户可能需要具体的代码示例,比如如何在Django中设置视图确保生成CSRF Cookie,以及小程序端如何正确发送请求头。 同时,需要注意用户可能对Django的配置不太熟悉,比如中间件的添加位置、CORS的设置等,所以需要给出具体的代码片段,并说明添加的位置。例如,在settings.py中启用中间件,配置CORS相关的参数,创建获取CSRF Token的视图等。 此外,用户可能在测试过程中遇到了问题,需要指导他们如何排查,比如使用开发者工具检查请求头、Cookie是否被正确携带,或者查看Django的日志确认是否有中间件拦截了请求。 最后,需要提醒用户安全相关的注意事项,比如在生产环境中启用HTTPS,定期刷新Token等,确保解决方案既有效又安全。</think>--- ### 🔍 **问题根源解析** 当Django服务返回"CSRF cookie not set"错误时,核心原因是客户端未正确携带CSRF令牌。以下是深度技术分析: **Django安全机制触发条件**: 1. 请求方法为`POST/PUT/PATCH/DELETE` 2. 未检测到有效的`csrftoken`(可能存在于Cookie或请求头) 3. 未通过`@csrf_exempt`显式豁免验证 --- ### 🛠️ **分步解决方案** #### **第一步:确认中间件配置** ```python # settings.py 必须包含 MIDDLEWARE = [ ... 'django.middleware.csrf.CsrfViewMiddleware', # 必须存在且未被注释 'corsheaders.middleware.CorsMiddleware', # 如果使用跨域请求 ... ] ``` #### **第二步:基础Cookie获取验证** ```python # views.py 创建测试接口 from django.http import JsonResponse from django.views.decorators.csrf import ensure_csrf_cookie @ensure_csrf_cookie def test_csrf(request): return JsonResponse({"message": "CSRF cookie已注入"}) ``` **验证方法**: ```bash curl -I -X GET http://your-domain.com/test_csrf/ # 应返回 Set-Cookie: csrftoken=xxxxxx; 字段 ``` #### **第三步:小程序端请求规范** ```javascript // 必须的请求头配置 wx.request({ url: 'https://your-domain.com/api/', method: 'POST', header: { 'X-CSRFToken': wx.getStorageSync('csrftoken'), // 从缓存读取 'Cookie': `csrftoken=${wx.getStorageSync('csrftoken')}` // 双重验证 }, data: { ... }, success(res) { ... } }) ``` --- ### ⚡ **高级调试技巧** #### **场景1:Cookie无法持久化** **现象**:每次请求获得不同的csrftoken **解决方案**: ```python # settings.py 添加 CSRF_COOKIE_SAMESITE = 'None' # 允许跨站携带 SESSION_COOKIE_AGE = 1209600 # 两周有效期(单位:秒) ``` #### **场景2:HTTPS环境异常** **现象**:开发环境正常,生产环境失败 **临时方案**: ```python # 生产环境临时调试(正式上线需关闭) CSRF_COOKIE_SECURE = False SESSION_COOKIE_SECURE = False ``` --- ### 📌 **关键配置检查表** ```python # 必须同步检查的设置项 CSRF_USE_SESSIONS = False # 禁用session模式 CSRF_COOKIE_HTTPONLY = False # 允许JS读取 CORS_ALLOW_CREDENTIALS = True # 跨域凭证 CORS_ALLOW_HEADERS = [ # 必要头信息 'x-csrftoken', 'content-type', 'authorization' ] ``` --- ### 🔥 **应急处理方案** 当遇到紧急故障时,可临时使用: ```python # views.py 临时豁免CSRF验证 from django.views.decorators.csrf import csrf_exempt @csrf_exempt def emergency_api(request): # 处理关键业务逻辑 return JsonResponse({"status": "紧急模式"}) ``` **注意**:此方案需在24小时内恢复安全验证 --- ### 📊 **CSRF验证流程图解** ``` 小程序启动 │ ├─ 发起GET请求 → Django服务器 │ │ │ ├─ 生成csrftoken │ └─ 通过Set-Cookie返回 │ └─ 存储token到Storage │ ├─ 后续POST请求携带 │ ├─ X-CSRFToken头 │ └─ Cookie头 │ └─ Django验证双令牌 ``` 通过上述配置验证流程,可彻底解决"CSRF cookie not set"问题。实际部署建议使用Postman先进行接口测试,再移植到小程序环境。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值