You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django REST同时使用Session与Token认证时CSRF Token异常问题咨询

解决Session与Token认证共存时的CSRF冲突问题

嘿,这个问题我太熟了——我之前帮好几个做跨端认证的团队踩过这个坑!本质上是你的服务端把Session认证的CSRF防护逻辑,不小心套到Token认证的路由上了,导致两种认证的状态互相干扰。咱们一步步拆解问题,再给你落地的解决方案:

冲突的根源到底是什么?

当你用Session登录第一个用户时,服务端会给浏览器种下sessionid Cookie,同时CSRF防护中间件会自动激活(毕竟Session是有状态的,必须防跨站请求伪造)。这时候你再发起Token登录请求,服务端检测到请求里带着之前的Session Cookie,就会默认触发CSRF校验,但Token登录的请求通常不会携带CSRF Token(因为前端没处理,或者Token认证本身不需要这层防护),自然就报错了。退出登录后Session Cookie被清空,CSRF校验的触发条件消失,问题也就没了。

具体解决方案(按优先级排序)

1. 给两种认证路由做精准隔离,控制CSRF校验范围

这是最根本的解决办法:把Session相关的路由和Token相关的路由彻底分开,只给Session路由套CSRF防护,Token路由完全跳过。

举个Node.js Express的例子:

const express = require('express');
const csrf = require('csurf');
const csrfProtection = csrf({ cookie: true });

const app = express();

// Session认证相关路由:必须过CSRF校验
app.use('/session/login', csrfProtection, sessionLoginHandler);
app.use('/session/logout', csrfProtection, sessionLogoutHandler);
app.use('/api/session', csrfProtection, sessionAuthMiddleware, sessionApiRoutes);

// Token认证相关路由:完全跳过CSRF校验
app.use('/token/login', tokenLoginHandler);
app.use('/api/token', tokenAuthMiddleware, tokenApiRoutes);

如果是Django的话,可以通过自定义中间件来跳过特定路由的CSRF校验:

from django.middleware.csrf import CsrfViewMiddleware

class SelectiveCSRFMiddleware(CsrfViewMiddleware):
    def process_view(self, request, view_func, view_args, view_kwargs):
        # 跳过Token相关路由的CSRF校验
        if request.path.startswith('/token/login/') or request.path.startswith('/api/token/'):
            return None
        return super().process_view(request, view_func, view_args, view_kwargs)

2. 调整认证中间件的优先级:Token优先于Session

让服务端先检查请求里有没有Token(比如Authorization: Bearer <your-token>),如果有就直接走Token认证流程,完全忽略Session和CSRF校验;只有当请求里没有Token时,再走Session认证和对应的CSRF防护。

这样即使请求里带着Session Cookie,只要有合法的Token,就不会触发CSRF校验,从根源上避免冲突。

3. 前端配合:切换认证方式时清理Session状态

前端层面可以提前规避这个问题:当用户从Session登录切换到Token登录时,先调用Session登出接口(或者直接设置Session Cookie过期),确保请求Token登录时,浏览器不会携带旧的Session Cookie。

比如用Axios发起Token登录请求时,可以设置不携带Cookie:

axios.post('/token/login', { username, password }, {
  credentials: 'omit' // 不携带任何Cookie,包括Session Cookie
});

4. 极端场景处理:允许同一用户同时用两种认证

如果你的业务允许同一用户同时在Web端用Session、移动端用Token,那要确保服务端的用户状态完全隔离:

  • Session的用户信息存在Session存储里
  • Token的用户信息存在Token的Payload里
    绝对不要让两种认证方式的用户状态互相覆盖或干扰。同时保持CSRF校验只绑定在Session路由上,Token路由完全独立。

这个问题对前端上线后的影响

很明确:如果不解决,用户在Web端用Session登录后,再用同一个浏览器打开你的H5页面走Token登录,就会触发CSRF报错,直接阻断登录流程,体验极差。所以必须在前端上线前搞定这个问题。

内容的提问来源于stack exchange,提问作者Zygro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:05:48