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

Vue3跨站前端应用对接Frappe框架的会话认证问题

Vue3 集成 Frappe Framework 认证与会话管理解决方案

一、修复生产环境CORS与SameSite Cookie问题

你的核心问题是跨站Cookie被拦截,根源是Frappe的会话Cookie配置和生产环境CORS规则不匹配,按以下步骤调整:

  1. 修改Frappe站点配置
    编辑Frappe站点的site_config.json文件,添加/更新以下配置项:

    {
      "allow_cors": true,
      "cors_allow_origins": ["https://你的Vue前端生产域名"],
      "session_cookie_samesite": "None",
      "session_cookie_secure": true
    }
    
    • session_cookie_samesite设为"None":解除跨站请求的Cookie限制,解决SameSite=Lax的拦截问题
    • session_cookie_secure设为true:要求Cookie仅在HTTPS环境下传输,这是SameSite=None的强制要求
    • cors_allow_origins指定前端精确域名,生产环境禁止用通配符*(会导致Allow-Credentials失效)
  2. 配置Nginx反向代理(若使用)
    如果Frappe通过Nginx对外提供服务,在Nginx配置中补充CORS相关响应头:

    location / {
      add_header Access-Control-Allow-Origin "https://你的Vue前端生产域名";
      add_header Access-Control-Allow-Credentials "true";
      add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
      add_header Access-Control-Allow-Headers "Content-Type, Authorization";
    
      # 预处理OPTIONS预检请求
      if ($request_method = OPTIONS) {
        return 204;
      }
    
      # 原Frappe代理配置
      proxy_pass http://frappe-server;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
    }
    

    修改后重启Nginx和Frappe服务。

二、Vue3前端登录请求配置

登录时必须确保请求携带Cookie,使用axios需开启withCredentials:

// 初始化带Cookie支持的axios实例
import axios from 'axios';

const frappeApi = axios.create({
  baseURL: 'https://你的Frappe服务器域名',
  withCredentials: true // 关键:允许跨域请求携带Cookie
});

// 登录方法
export async function frappeLogin(usr, pwd) {
  try {
    const res = await frappeApi.post('/api/method/login', { usr, pwd });
    if (res.status === 200) {
      return res.data;
    }
    throw new Error('登录失败');
  } catch (err) {
    throw err.response?.data?.message || err.message;
  }
}

三、会话管理与后续API调用

所有后续接口请求复用同一个frappeApi实例,它会自动携带Frappe的会话Cookie(sid):

// 获取当前登录用户信息
export async function getCurrentUser() {
  try {
    const res = await frappeApi.get('/api/method/frappe.auth.get_logged_user');
    return res.data.message; // 返回登录用户名
  } catch (err) {
    // 会话过期或未登录时返回null
    return null;
  }
}

// 示例:调用自定义Frappe方法
export async function callCustomMethod(methodName, params) {
  try {
    const res = await frappeApi.post(`/api/method/${methodName}`, params);
    return res.data.message;
  } catch (err) {
    throw err.response?.data?.message || err.message;
  }
}

四、登录状态校验

通过frappe.auth.get_logged_user接口校验登录状态,结合Vue路由守卫实现页面权限控制:

// router/index.js
import { createRouter, createWebHistory } from 'vue-router';
import { getCurrentUser } from '../api/frappe';

const router = createRouter({
  history: createWebHistory(),
  routes: [
    { path: '/', component: () => import('../views/Home.vue') },
    { path: '/login', component: () => import('../views/Login.vue') },
    // 需要登录权限的页面
    { 
      path: '/dashboard', 
      component: () => import('../views/Dashboard.vue'),
      meta: { requiresAuth: true } 
    }
  ]
});

// 全局路由守卫
router.beforeEach(async (to, from, next) => {
  if (to.meta.requiresAuth) {
    const user = await getCurrentUser();
    if (!user) {
      // 未登录时跳转到登录页
      next('/login');
    } else {
      next();
    }
  } else {
    next();
  }
});

export default router;

五、登出功能

调用Frappe的logout接口清除会话,同时清理前端缓存的用户信息:

export async function frappeLogout() {
  try {
    await frappeApi.post('/api/method/logout');
    // 清除前端可能存储的用户数据
    localStorage.removeItem('currentUser');
    return true;
  } catch (err) {
    throw err.response?.data?.message || err.message;
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 02:15:09