Vue3跨站前端应用对接Frappe框架的会话认证问题
Vue3 集成 Frappe Framework 认证与会话管理解决方案
一、修复生产环境CORS与SameSite Cookie问题
你的核心问题是跨站Cookie被拦截,根源是Frappe的会话Cookie配置和生产环境CORS规则不匹配,按以下步骤调整:
修改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失效)
配置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
相关产品推荐
相关产品推荐

