这是因为 JWT认证与CSRF校验的设计逻辑完全不同,当全局启用JWT认证后,Django的CSRF校验会被“绕过”或不再生效,具体原因如下:
核心原因:JWT认证不依赖Cookie,无需CSRF保护
1. CSRF的作用场景
CSRF攻击的前提是:攻击者利用用户的浏览器Cookie(如Session ID)伪造请求。因此,Django的CSRF校验本质是为了防御“基于Cookie的认证”(如Session认证)被滥用。
2. JWT认证的特性
JWT认证的核心是前端在请求头中携带Token(如 Authorization: Bearer ),而不是依赖Cookie传递身份信息。
由于JWT不使用Cookie,攻击者无法通过伪造Cookie来发起CSRF攻击,因此CSRF校验对JWT认证来说是多余的。
为什么开启JWT全局认证后,CSRF失败会消失?
当项目全局启用JWT认证(例如通过DRF的 DEFAULT_AUTHENTICATION_CLASSES 配置),通常会同时满足以下条件,导致CSRF校验不再触发:
1. 视图默认关闭CSRF(如DRF视图)
若使用Django REST Framework(DRF)实现JWT认证,DRF的 APIView 等视图类默认会关闭CSRF校验(通过重写 dispatch 方法,跳过 CsrfViewMiddleware 的检查)。
因此,即使不手动添加 @csrf_exempt ,这些视图也不会校验CSRF。
2. JWT认证优先于Session认证
当全局配置JWT为默认认证方式时,Django会优先通过请求头的Token验证身份,而非依赖Cookie中的Session ID。
此时,CSRF校验的触发条件(基于Cookie的认证)不满足,自然不会报错。
总结
- Session认证:依赖Cookie,必须通过CSRF校验防御攻击(需传递 X-CSRFToken 或关闭校验)。
- JWT认证:依赖请求头Token,不依赖Cookie,CSRF攻击无效,因此DRF等框架会默认关闭CSRF校验,避免多余的安全检查。
这就是为什么开启JWT全局认证后,接口不再报CSRF失败的根本原因——两者的安全机制互不依赖,JWT天然规避了CSRF的攻击场景。