
在 src/router/index.js 中添加路由:
import Login from '../pages/login.vue';
const routes = [
// ...
{
path: '/login',
name: 'Login',
component: Login,
hidden: true,
},
];
登录页面 src/pages/Login.vue 中添加登录逻辑:
function handleLogin () {
formRef.value.validate(async valid => {
if (!valid) {
console.log('invalid');
return false;
}
loading.value = true;
const { code, message } = await useStore.login(loginForm);
loading.value = false;
if (code === 0) {
router.replace(toPath || '/');
} else {
message.error(message);
}
})
}
mock 登录接口:
const mockAPI = {
login: {
url: '/user/login',
type: 'POST',
response: config => {
const { username, password } = config.body;
const token = `token-${username}`;
if (password !== `${username}123`) {
return {
code: 200,
message: 'Account or password is incorrect',
};
}
return {
code: 200,
data: {
token,
}
};
}
}
};
登录成功后,需要把这个 token 存储在本地存储里面,留着后续发送数据。实现比较简单,直接把 token 存储到 localStorage 中就行。
拿到 token 后,为了进行接口权限认证,要把 token 放在 HTTP 请求的 header 内部。
service.interceptors.request.use(
(config) => {
if (store.getters.token) {
config.headers['X-Token'] = getToken();
}
return config;
},
(error) => {
console.log(error);
return Promise.reject(error);
},
);
上面只是解决了网络请求的拦截,还可以使用 Vue-Router 的 导航守卫实现对页面的拦截。
router.beforeEach(async (to, from, next) => {
const token = getToken();
if (to.path !== '/login') {
if (token) {
next();
} else {
next('/login');
}
} else {
next();
}
});
之前开发项目的时候,和登录注册相关的配置,不需要自己管理 token,都是后端直接设置 cookie。
但是,在现在这种前后端分离的场景下,通常前后端项目都会部署在不同的机器和服务器之上,Cookie 在跨域上有诸多的限制。所以在这种场景下,更适合手动地去管理权限,于是就诞生了现在流行的基于 token 的权限解决方案,也可以把 token 理解为手动管理的 cookie。
在管理系统开发中,订单页面是所有人都可以看到的,但是像账单的查询页面,以及其他一些权限更高的页面,需要管理员权限才能看到。这时候,就需要对系统内部的权限进行分级,每个级别都对应着可以访问的不同页面。
通常使用的权限解决方案就是 RBAC 权限管理机制。简单来说,就是在下图所示的这个模型里,除了用户和页面之外,需要一个新的概念,就是角色。每个用户有不同的角色,每个角色对应不同的页面权限,这个数据结构的关系设计主要是由后端来实现。

在用户登录完成之后会获取页面的权限数据,也就是说后端会返回当前页面的动态权限部分。
这样有一部分页面路由是写在代码的 src/router/index.js 中,另外一部分页面路由通过 axios 获取数据后,通过调用 vue-router 的 addRoute 方法动态添加进项目整体的路由配置中。
可以在 Vuex 中注册 addRoute 这个 action,通过后端返回的权限页面数据,调用 router.addRoute 新增路由。
addRoutes({ commit }, accessRoutes) {
const removeRoutes = [];
accessRoutes.forEach((route) => {
const removeRoute = router.addRoute(route);
removeRoutes.push(removeRoute);
});
commit('SET_ROUTES', accessRoutes);
}
与新增路由对应,在页面重新设置权限的时候,需要用 router.removeRoute 来删除注册的路由,这也是上面的代码中还有一个 removeRoutes 来管理动态路由的原因。
需要把动态路由的状态存储在本地存储里,否则刷新页面之后,动态的路由部分就会被清空,页面就会显示 404 报错。
需要在 localStorage 中把静态路由和动态路由分开对待,在页面刷新的时候,通过 src/router/index.js 入口文件中的 routes 配置,从 localStorage 中获取完整的路由信息,并且新增到 vue-router 中,才能加载完整的路由。