基于 Vue 和 Vuex 的后台登录与动态权限路由实现
在构建中后台管理系统时,权限控制和安全性是系统的核心基石。一个成熟的方案通常需要实现:根据用户权限动态过滤路由表,并同步生成侧边栏菜单。本文将探讨如何通过 Token 机制和 Vue 路由守卫实现这一套完整的鉴权流程。
鉴权流程设计思路
整个鉴权过程可以分为登录鉴权和权限加载两个阶段:
- 登录鉴权:用户提交凭据后,服务端验证合法性并返回身份标识(Token)。前端将 Token 持久化存储在 Cookie 或 LocalStorage 中,以维持会话状态。
- 身份校验:在路由跳转前,通过 Token 请求用户信息接口(获取角色 Role、权限列表等)。根据角色计算出该用户拥有的异步路由,并通过
router.addRoute动态挂载。
为了确保状态的一致性,建议使用 Vuex 或 Pinia 全局状态管理来维护用户信息和路由表。
登录逻辑的实现
当用户触发登录操作时,前端通过 Action 提交登录请求。成功获取 Token 后,将其存入状态管理库和浏览器持久化缓存中。
// 视图层调用登录接口
async function handleUserAuth() {
try {
await this.$store.dispatch('account/authenticate', this.loginData);
// 登录成功后跳转至重定向页面或首页
this.$router.push({ path: this.redirect || '/' });
} catch (error) {
this.$message.error('身份验证失败,请检查账号密码');
}
}
// Vuex Action 实现
const actions = {
authenticate({ commit }, credentials) {
const { account, password } = credentials;
return new Promise((resolve, reject) => {
api.login(account.trim(), password)
.then(response => {
const { token } = response.data;
// 将 Token 存入 Cookie,设置有效期
Cookies.set('Admin-Token', token);
commit('UPDATE_TOKEN', token);
resolve();
})
.catch(err => reject(err));
});
}
};
全局路由守卫与动态权限加载
在页面刷新或切换路由时,利用 router.beforeEach 钩子拦截请求。如果本地存在 Token 但 Vuex 中尚未加载用户信息,则触发信息获取流程。
router.beforeEach(async (to, from, next) => {
const hasToken = getToken();
if (hasToken) {
if (to.path === '/login') {
next({ path: '/' });
} else {
const hasPermissions = store.getters.userRoles && store.getters.userRoles.length > 0;
if (hasPermissions) {
next();
} else {
try {
// 获取当前用户的详细权限信息
const { roles } = await store.dispatch('account/fetchUserProfile');
// 根据角色生成可访问的路由表
const accessRoutes = await store.dispatch('permission/generateRoutes', roles);
// 动态注入路由
accessRoutes.forEach(route => {
router.addRoute(route);
});
// 确保路由挂载完成后再进行跳转
next({ ...to, replace: true });
} catch (err) {
// 异常情况下强制注销并重定向至登录页
await store.dispatch('account/resetToken');
next(`/login?redirect=${to.path}`);
}
}
}
} else {
// 无 Token 的情况下,判断是否在白名单中
isWhiteList(to.path) ? next() : next(`/login?redirect=${to.path}`);
}
});
存储策略的选择
在实际应用中,不建议将完整的用户信息(如权限列表、用户名)直接存储在本地缓存。主要原因如下:
- 数据一致性:若用户在其他终端修改了资料,本地缓存的过期数据会导致界面显示异常。
- 安全性:权限信息应由服务端实时下发,前端仅负责持久化 Token。
因此,最佳实践是:仅在 Cookie 中保留 Token。每当页面刷新(Vuex 状态重置)时,通过 Token 重新向后端请求最新的 user_info。这种方案在微服务架构下尤为适用,它确保了每一次会话都能获取到最精准的权限视图。