DRF的POST请求无需携带CSRF令牌即可正常运行,是否存在安全风险?
为什么DRF接口不带CSRF令牌也能正常通过请求校验
- 首先要明确CSRF防护的核心设计初衷:Django原生的CSRF校验,是专门针对基于Cookie/Session的身份认证场景打造的安全机制。这类场景下浏览器会自动携带目标域名下的Cookie发起请求,攻击者可以构造恶意页面诱导已登录用户触发跨域请求,因此需要CSRF令牌校验请求的真实合法性。
- 很多人误以为DRF默认全局关闭了CSRF校验,实际上DRF只是把CSRF的触发逻辑和接口的认证方式做了更合理的绑定:
- 当接口走
SessionAuthentication、BasicAuthentication这类依赖请求携带的Cookie做身份识别的认证流程时,DRF会强制启用Django原生的CSRF校验,没带合法CSRF令牌就会返回403响应。 - 当接口走
TokenAuthentication、JWTAuthentication这类通过自定义请求头传递身份凭证的认证流程时,DRF会自动对这类请求做CSRF豁免,不会强制要求携带CSRF令牌。
- 当接口走
- 这套逻辑本质是从安全根因出发的设计:CSRF攻击能够成立的核心前提是“服务端仅依赖浏览器自动携带的Cookie识别用户身份,无法区分请求是否是用户主动发起”。而基于自定义请求头传Token的认证方式下,浏览器不会自动把这类自定义头信息附加到跨域请求里,攻击者既没法拿到用户存在本地的Token,也没法构造出带合法
Authorization头的恶意请求,从机制上就不存在CSRF攻击的基础,自然不需要额外加CSRF校验流程。
这种运行状态是否安全
- 只要你的接口身份认证逻辑不依赖Cookie自动传参,这种不带CSRF令牌的运行状态是完全安全的,符合API开发的通用安全规范。
- 结合你给出的前端调用逻辑来看,你是从
localStorage中读取登录态的Token,手动放到请求头Authorization字段中传递给服务端,全程没有依赖Cookie传递身份凭证,完全匹配DRF对Token认证的CSRF豁免逻辑,不存在CSRF层面的安全风险。 - 但需要注意几个容易引发安全问题的误区:
- 不要图省事把认证Token放到Cookie中存储,还不配置
HttpOnly、SameSite、Secure等安全属性。一旦身份凭证完全依赖浏览器自动携带的Cookie传递,就会回到CSRF攻击的适用场景,必须重新开启CSRF校验才能保障安全。 - 要确认对应接口的权限配置:哪怕认证机制本身没有CSRF风险,如果接口被设置为匿名可访问,任何人都可以不带凭证调用创建群组、修改用户信息这类敏感接口,依然会存在数据安全问题。
- 不要随意改动DRF的认证类顺序:如果把
SessionAuthentication放到认证类列表的最前面,当已登录Django后台的用户访问API时,DRF会自动触发Session认证流程,这时候如果不带CSRF令牌,接口会直接返回403,反而会出现和你预期不符的鉴权问题。
- 不要图省事把认证Token放到Cookie中存储,还不配置
你当前的前端调用实现代码:
createGroup=()=>{ let store = JSON.parse(localStorage.getItem('login')) var url = 'http://127.0.0.1:8000/myapi/creategroup/' fetch(url,{ method:'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Token '+store.token, }, body:JSON.stringify({ 'name':this.state.groupName, }) }) .then((response)=>{ response.json() document.getElementById('i').value='' this.setState({groupName:''}) }) }
额外代码提示:你当前的fetch链式调用存在逻辑问题:第一个
.then回调里没有返回response.json()的解析结果,后续流程是拿不到接口返回的实际数据的,建议调整为fetch(...).then(response => response.json()).then(data => { /* 处理接口返回逻辑 */ })的结构。
内容的提问来源于stack exchange,提问作者Asif Biswas
相关产品推荐
相关产品推荐

