登录状态管理核心是“状态可读+守卫可判+拦截可控”,用Pinia统一存储并持久化token与用户信息,守卫中同步读取isLogin判断,全局前置守卫集中处理未登录跳转,配合后端权限校验与按钮级指令防越权。

登录状态管理与路由守卫配合,核心是“状态可读 + 守卫可判 + 拦截可控”。关键不在于存不存 token,而在于守卫能否实时、准确地拿到当前用户是否已登录的结论。
状态存储:用 Pinia 统一维护,避免 localStorage 误判
把登录态(如 token、userInfo)存在 Pinia 的 userStore 中,并开启持久化(如 pinia-plugin-persistedstate),这样刷新页面后状态不丢失。不要只依赖 sessionStorage 或手动读 localStorage —— 守卫里若直接读 localStorage,容易和 store 不同步,尤其在异步登录完成但 store 还没更新时出错。
示例逻辑:
- 登录成功后:调用 userStore.login({ token, userInfo }),内部自动写入 store 并持久化
- 登出时:调用 userStore.logout(),清空 store 和本地缓存
- 守卫中始终通过 useUserStore().isLogin 或 !!useUserStore().token 判断,不手撕 localStorage
全局前置守卫:登录拦截主战场
在 router.beforeEach 中集中处理未登录跳转。重点不是“拦谁”,而是“放行谁”:
审查 Vue 管理后台的变更请求(Vue 2 + Element UI,Vue 3 + Element Plus)。重点关注最小化变更实现、上线风险检查以及回归检查清单生成。
立即学习“前端免费学习笔记(深入)”;
- 目标路由是 /login 或 /register 等公开页 → 直接 next()
- 目标路由标记了 meta.requiresAuth: true(或类似字段)→ 检查 userStore 是否已登录
- 未登录 → return { path: '/login', query: { redirect: to.fullPath } },保留来源路径,登录后可跳回
- 已登录 → next()
注意:不要在守卫里调用异步 action(如 fetchUserInfo)再判断——这会阻塞导航。登录态必须是同步可得的。
补充校验:防止绕过(如手动输 URL)
仅靠前端守卫不能杜绝越权,但可提升体验和安全性:
- 每次进入需权限的页面前,组件内可调用 userStore.fetchProfile() 补充加载角色/权限数据(非阻塞)
- 接口请求统一加拦截器,携带 token;后端必须二次校验权限,前端守卫只是第一道体验屏障
- 对敏感操作(如删除、导出),按钮级再加 v-permission 指令,无权限直接隐藏
常见陷阱提醒
几个高频翻车点:
- store 初始化时机晚于守卫执行:确保 Pinia 实例在 router 之前创建并安装,且 userStore 在首次访问时已定义(非懒加载)
- token 过期未及时清理:登录时存过期时间,在守卫中检查 Date.now() > expiresAt,过期则清空 store 并跳登录
- 重定向死循环:/login 页面自身不能 requireAuth,否则守卫发现未登录 → 跳 /login → 守卫再发现未登录 → 再跳 /login…


















