vue-element-admin用户权限管理,根据用户权限获取动态路由,刷新页面需重新登录bug处理
vue-element-admin用户角色权限,刷新跳转登录页面问题的主要原因是用户角色登录的时候就获取到了,起初没有另外的接口再去获取用户信息,后来新增一个通过用户id再去获取用户角色,但跟原框架通过token获取用户角色不同,就又冒出刷新页面却跳到登录页面去了的问题这里通过一个流程图展示src/promission.js的router.beforeEach的运行逻辑(必须要2这条线才能获取..
vue-element-admin用户权限管理,根据不同用户获取动态路由,刷新页面需重新登录bug处理
问题的主要原因是用户角色登录的时候就获取到了,起初没有另外的接口再去获取用户信息。其实在登录的时候,不能给角色赋值,否则执行有token无roles这一步,就获取不到动态路由。
后来新增一个接口通过用户id再去获取用户角色,但跟原框架通过token获取用户角色不同,就又冒出每次刷新页面却跳到登录页面去了的问题,这个通过localStorage来处理。
这里通过一个流程图展示src/promission.js的router.beforeEach的运行逻辑(必须要2这条线才能获取到动态路由):
根据用户权限动态加载路由涉及文件有 src/promission.js ,router.beforeEach内容使用模板本身的就行。
router.beforeEach(async (to, from, next) => {
// start progress bar
NProgress.start();
// set page title
document.title = getPageTitle(to.meta.title);
// determine whether the user has logged in
const hasToken = getToken();
if (hasToken) {
if (to.path === "/login") {
// if is logged in, redirect to the home page
next({ path: "/" });
NProgress.done();
} else {
const hasRoles = store.getters.roles && store.getters.roles.length > 0;
if (hasRoles) {
next();
} else {
try {
// get user info
// note: roles must be a object array! such as: ['admin'] or ,['developer','editor']
const { roles } = await store.dispatch("user/getInfo");
// generate accessible routes map based on roles
const accessRoutes = await store.dispatch(
"permission/generateRoutes",
roles
);
// dynamically add accessible routes
router.addRoutes(accessRoutes);
// hack method to ensure that addRoutes is complete
// set the replace: true, so the navigation will not leave a history record
next({ ...to, replace: true });
} catch (error) {
// remove token and go to login page to re-login
await store.dispatch("user/resetToken");
Message.error(error || "Has Error");
next(`/login?redirect=${to.path}`);
NProgress.done();
}
}
}
} else {
/* has no token*/
if (whiteList.indexOf(to.path) !== -1) {
// in the free login whitelist, go directly
next();
} else {
// other pages that do not have permission to access are redirected to the login page.
next(`/login?redirect=${to.path}`);
NProgress.done();
}
}
});
我在这里的问题主要是在登录的时候就获取角色,其实这里不能给角色赋值,否则就不能进入第2二条线,获取不到动态路由。
文件 store/modules/user.js
action中 的 login() ,获取 token和 id,这里使用 localStorage 是为了解决通过id获取roles导致的 刷新页面却跳到登录页面并有错误警告 的问题。
login({ commit }, userInfo) {
const { username, password } = userInfo;
return new Promise((resolve, reject) => {
login({
username: username.trim(),
password: password
})
.then(response => {
const { data } = response;
commit("SET_TOKEN", data.token);
commit("SET_USERID", data.user.id);
// 储存id,刷新页面时调用
localStorage.setItem("userId", JSON.stringify(data.user.id));
setToken(data.token);
resolve();
})
.catch(error => {
reject(error);
});
});
}
action中 的 getInfo() , 获取 roles,这里JSON.parse(localStorage.getItem(“userId”)) 释放储存在localStorage中的id,并传给getInfo接口(我这里的接口接收的参数是id而不是token),否则刷新页面的时候会执行router.beforeEach的第2条线时id不存在,导致需要重新登录还报错,因为token是储存在cookie当中的,而后设的id并没有储存在cookie中,所以刷新页面的时候只有token没有id,getInfo这个就执行不成功。localStorage就是解决这个问题的。
getInfo({ commit, state }) {
const id = JSON.parse(localStorage.getItem("userId"));
commit("SET_USERID", id);
return new Promise((resolve, reject) => {
getInfo(state.id)
.then(response => {
// debugger;
const { data } = response;
if (!data) {
reject("Verification failed, please Login again.");
}
const { roles } = data;
if (!roles || roles.length <= 0) {
reject("getInfo: roles must be a non-null array!");
}
commit("SET_ROLES", roles);
resolve(data);
})
.catch(error => {
reject(error);
});
});
},
下面补充2点
要将src/router/index.js里面的路由分为 2 部分,constantRoutes是不需要权限都能访问的路由比如登录,404等页面,asyncRoutes放需要权限控制的路由,并在路由的 mate中添加 roles属性,roles放有访问权限的角色
import Vue from "vue";
import Router from "vue-router";
Vue.use(Router);
/**
* constantRoutes
* a base page that does not have permission requirements
* all roles can be accessed
*/
export const constantRoutes = [
{
path: "/login",
component: () => import("@/views/login/index"),
hidden: true
},
{
path: "/404",
component: () => import("@/views/404"),
hidden: true
}
];
/**
* asyncRoutes
* the routes that need to be dynamically loaded based on user roles
*/
export const asyncRoutes = [
{
path: "/",
component: () => import("@/views/dashboard/index"),
redirect: "/dashboard",
children: [
{
path: "dashboard",
name: "Dashboard",
hidden: true,
meta: { title: "主页", affix: true }
}
]
},
{
path: "/dashboard/firm",
name: "firm",
component: firm,
hidden: true,
meta: { roles: ["admin", "user"] }
},
{
path: "/dashboard/map",
name: "map",
component: map,
hidden: true,
meta: { roles: ["admin"] }
},
// 404 page must be placed at the end !!!
{ path: "*", redirect: "/", hidden: true }
];
const createRouter = () =>
new Router({
// mode: "history", // require service support
scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes
});
const router = createRouter();
// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
export function resetRouter() {
const newRouter = createRouter();
router.matcher = newRouter.matcher; // reset router
}
export default router;
src/layout/components/Sidebar/index中循环的routes需要换成permission_routes,permission_routes在src/store/getter中定义
<sidebar-item v-for="route in permission_routes"
:key="route.path"
:item="route"
:base-path="route.path" />
computed: {
...mapGetters(["permission_routes", "sidebar"]),
更多推荐
所有评论(0)