Django Session Auth与DRF Knox JWT共存时先登Session后调API返回403问题
问题根因
- CSRF校验拦截:Django对所有携带有效session cookie的非GET请求,默认强制校验CSRF令牌。你先完成Session登录后,客户端会自动携带
sessionidcookie,此时调用POST类型的JWT登录接口时如果没有附带当前session对应的CSRF令牌,Django会直接返回403。反过来先获取JWT再走Session登录时,Session登录流程一般会主动传递CSRF令牌,所以不会触发报错。 - 登录接口权限配置错误:如果你的JWT登录接口没有单独设置
permission_classes = [AllowAny],继承了全局的IsAuthenticated权限,或是你自定义了“仅未认证用户可访问登录接口”的权限规则,已通过Session登录的用户访问接口时会被权限类拦截。 - 认证类顺序冲突:如果全局认证配置中
SessionAuthentication顺序早于Knox JWT认证类,已登录用户的请求会优先被识别为Session认证状态,若你的JWT登录逻辑中存在“仅未认证用户可申请令牌”的校验,就会主动返回403。
修复方案
- 处理CSRF校验问题:
- 方案1:给JWT登录接口单独豁免CSRF校验,函数视图加
@csrf_exempt装饰器,类视图用method_decorator(csrf_exempt, name='dispatch')修饰即可。 - 方案2:调用JWT登录接口时,从cookie中提取
csrftoken的值,放到请求头X-CSRFToken中传递,满足Django的校验要求。
- 方案1:给JWT登录接口单独豁免CSRF校验,函数视图加
- 修正权限配置:显式给JWT登录接口设置
permission_classes = [AllowAny],如果有自定义的未登录校验规则,可以兼容已登录场景:用户已登录时直接返回对应用户的有效JWT令牌,无需走登录校验逻辑。 - 调整认证类配置:要么把Knox JWT认证类的优先级调到
SessionAuthentication前面,要么给JWT登录接口单独设置authentication_classes = [],避免接口提前识别用户认证状态触发不必要的拦截。
内容的提问来源于stack exchange,提问作者Adrian0012
相关产品推荐
相关产品推荐

