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

Vue.js与Django认证会话保持失败求助:用request jar仍遇403错误

会话持久化问题排查与解决方案

我来帮你搞定这个会话无法持久的问题,你遇到的403错误大概率和CSRF令牌处理、会话Cookie的保存/发送逻辑有关,咱们一步步来解决:

1. 先解决CSRF令牌的核心问题

虽然你的Login视图加了csrf_exempt,但后续被user_login_required保护的视图默认会校验CSRF令牌(除非你也给它们加了csrf_exempt,但这非常不安全)。Django的会话认证依赖CSRF Cookie和请求头里的CSRF令牌配对,而你当前的代码没处理这个流程,这是403的主要原因。

修复步骤:

  • 登录前先向Django获取CSRF令牌Cookie
  • 登录时同时发送账号密码和CSRF令牌请求头

修改你的Vue代码:

var request = require('request');

// 新增:获取CSRF令牌的方法
get_csrf_token() {
  return new Promise((resolve, reject) => {
    // 先发送GET请求获取Django的CSRF Cookie
    request({
      url: '/api/get-csrf-token/', // 需要在Django中新增这个接口
      jar: this.get_jar(),
      method: 'GET'
    }, (err, res) => {
      if (err) reject(err);
      // 从jar中提取csrftoken值
      const cookieStr = this.get_jar().getCookieString(res.request.uri);
      const csrfToken = cookieStr.split(';').find(item => item.trim().startsWith('csrftoken='))?.split('=')[1];
      resolve(csrfToken);
    });
  });
}

// 修改send_ajax,支持传入CSRF令牌
send_ajax(url, data, method, callback, csrfToken = null) {
  const options = {
    url: url,
    method: method,
    form: data,
    jar: this.get_jar(),
    headers: {}
  };
  // 有CSRF令牌时,添加到请求头
  if (csrfToken) {
    options.headers['X-CSRFToken'] = csrfToken;
  }
  request(options, function(err, res, body){
    callback(err, res, body)
  });
}

// 调整登录流程:先拿CSRF令牌再登录
async login(email, password) {
  try {
    const csrfToken = await this.get_csrf_token();
    this.send_ajax('/api/login/', {email, password}, 'POST', (err, res, body) => {
      if (res.statusCode === 200) {
        console.log('登录成功');
        // 后续请求复用同一个jar和CSRF令牌
        this.send_ajax('/api/protected/', {}, 'GET', (err, res, body) => {
          // 这里应该能正常访问受保护接口了
        }, csrfToken);
      }
    }, csrfToken);
  } catch (err) {
    console.error('获取CSRF令牌失败:', err);
  }
}

在Django中新增获取CSRF令牌的接口:

from django.views.decorators.csrf import ensure_csrf_cookie
from django.http import JsonResponse

@ensure_csrf_cookie
def get_csrf_token(request):
    return JsonResponse({'message': 'CSRF Cookie已设置'})

别忘了在urls.py中给这个接口配置路由。

2. 检查Django的会话Cookie配置

打开settings.py,确保会话相关配置正确,尤其是跨域、SameSite属性:

# settings.py
SESSION_COOKIE_SAMESITE = 'Lax'  # 同域场景用Lax即可,跨域场景需设为None(同时要开启SESSION_COOKIE_SECURE=True)
SESSION_COOKIE_HTTPONLY = False  # 测试阶段先设为False,确保jar能捕获Cookie(线上环境可改回True)
SESSION_COOKIE_DOMAIN = None  # 同域留空,跨域需设置为前端域名
SESSION_ENGINE = 'django.contrib.sessions.backends.db'  # 确保用默认的数据库会话引擎

3. 确保Jar全局复用

检查你的Vue组件中this.jar是否在多实例中被重复创建。最好把Jar放在全局状态管理(比如Vuex)或者单例工具类中,确保所有请求共用同一个Jar:

// 单独创建api.js工具文件
const request = require('request');
let globalJar = null;

export function getGlobalJar() {
  if (!globalJar) {
    globalJar = request.jar();
  }
  return globalJar;
}

// 所有请求都调用这个方法获取Jar

4. 验证会话Cookie是否被正确保存

在登录回调中打印Jar内的Cookie,确认是否包含Django的sessionid和csrftoken:

this.send_ajax('/api/login/', {email, password}, 'POST', (err, res, body) => {
  console.log('Jar内的Cookie:', this.get_jar().getCookieString(res.request.uri));
  // 正常情况下应该看到类似:sessionid=xxxx; csrftoken=xxxx
}, csrfToken);

如果看不到sessionid,说明Django的login(request, user)没有正确设置会话Cookie,需要检查Django的会话引擎配置是否正常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 03:58:43