用户前台登录后,后台返回一个token,将该token存储到store中,并设置到header中,每次发起请求时都会携带该token,用于后台进行权限校验
// 登录方法 login.vue
handleLogin() {
this.$refs.loginForm.validate((valid) => {
if (valid) {
this.loading = true;
this.$store
.dispatch("user/login", this.loginForm)
.then(() => {
this.$router.push({ path: this.redirect || "/" });
this.loading = false;
})
.catch(() => {
this.loading = false;
});
} else {
console.log("error submit!!");
return false;
}
});
},
在store 的user.js中定义了该方法
login({ commit }, userInfo) {
const { userName, userPassword } = userInfo;
return new Promise((resolve, reject) => {
login({ userName: userName.trim(), userPassword: userPassword })
.then((response) => {
const { data } = response;
commit("SET_TOKEN", data.token);
setToken(data.token);
resolve();
})
.catch((error) => {
reject(error);
});
});
},
const mutations = {
RESET_STATE: (state) => {
Object.assign(state, getDefaultState());
},
SET_TOKEN: (state, token) => {
state.token = token;
},
SET_NAME: (state, name) => {
state.name = name;
},
SET_AVATAR: (state, avatar) => {
state.avatar = avatar;
},
SET_AUTHORITIES: (state, authorities) => {
state.authorities = authorities;
},
};
此时登录成功后,后台将返回一个token
在请求拦截器中将token添加到请求头上,在响应拦截器中设置未登录状态访问时跳转到登录页面
import axios from "axios";
import { MessageBox, Message } from "element-ui";
import store from "@/store";
import { getToken, removeToken } from "@/utils/auth";
import router from "@/router";
// create an axios instance
const service = axios.create({
baseURL: "http://localhost:8080", // url = base url + request url
timeout: 5000, // request timeout
});
// request interceptor
service.interceptors.request.use(
(config) => {
if (store.getters.token) {
config.headers["token"] = getToken();
}
return config;
},
(error) => {
console.log(error);
return Promise.reject(error);
}
);
// response 拦截器
service.interceptors.response.use(
(response) => {
const res = response.data;
// if the custom code is not 20000, it is judged as an error.
if (res.code !== 200 && res.code !== 201) {
Message({
message: res.message || "Error",
type: "error",
duration: 5 * 1000,
});
// 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
// to re-login
MessageBox.confirm(
"You have been logged out, you can cancel to stay on this page, or log in again",
"Confirm logout",
{
confirmButtonText: "Re-Login",
cancelButtonText: "Cancel",
type: "warning",
}
).then(() => {
store.dispatch("user/resetToken").then(() => {
location.reload();
});
});
}
if (res.code == 401) {
removeToken();
router.replace({
path: "/login",
});
}
return Promise.reject(new Error(res.message || "Error"));
} else {
return res;
}
},
(error) => {
console.log("err" + error); // for debug
Message({
message: error.message,
type: "error",
duration: 5 * 1000,
});
return Promise.reject(error);
}
);
export default service;
在permission.js 中进行相关代码编写 (获取用户的信息,动态路由的生成加载)
router.beforeEach()路由拦截()
import router from "./router";
import store from "./store";
import { Message } from "element-ui";
import NProgress from "nprogress"; // progress bar
import "nprogress/nprogress.css"; // progress bar style
import { getToken } from "@/utils/auth"; // get token from cookie
import getPageTitle from "@/utils/get-page-title";
NProgress.configure({ showSpinner: false }); // NProgress Configuration
const whiteList = ["/login"]; // no redirect whitelist
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();
const hasRoles =
store.state.user.authorities && store.state.user.authorities.length > 0;
// 如果有token再跳转到登录页面时,根据获取的角色信息进行页面跳转
if (hasToken) {
if (to.path === "/login") {
if (store.state.user.authorities) {
if (store.state.user.authorities.includes("ROLE_ADMIN")) {
next({ path: "/" });
} else {
next({ path: "/user" });
}
} else {
next({ path: "/" });
}
NProgress.done();
} else {
// 获取登录用户名 如果用户名存在说明用户已经登录且获得了用户信息,直接放行,如果没有用户名,就进行用户信息获取
const hasGetUserInfo = store.getters.name;
if (hasGetUserInfo) {
next();
} else {
try {
//判断用户角色是否存在
if (!hasRoles) {
let userInfo = await store.dispatch("user/getInfo"); // 获取用户信息
// 根据获得到的用户信息,获取用户角色信息并动态生成路由
let routes = await store.dispatch(
"permission/getAsyncRoutes",
userInfo.user.authorities
);
router.options.routes = routes;
router.addRoutes(routes); // 将生成的动态路由添加到原先的路由中
next({ ...to, replace: true }); // 保证路由已挂载
// 根据用户角色进行登录后的首页面跳转
if (store.state.user.authorities) {
if (store.state.user.authorities.includes("ROLE_ADMIN")) {
next({ path: "/" });
} else {
next({ path: "/user/user" });
}
}
}
} catch (error) {
// remove token and go to login page to re-login
await store.dispatch("user/resetToken");
Message.error(error || "Has Error");
next(`/login`);
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`);
NProgress.done();
}
}
});
router.afterEach(() => {
// finish progress bar
NProgress.done();
});
获取用信息的方法定义在store的user.js中
// 获取用户信息
getInfo({ commit, state }) {
return new Promise((resolve, reject) => {
getInfo()
.then((response) => {
const { data } = response;
if (!data) {
return reject("Verification failed, please Login again.");
}
const { username, authorities } = data.user;
// 将用户名,和用户角色信息存储到store中
commit("SET_NAME", username);
commit("SET_AUTHORITIES", authorities);
resolve(data);
})
.catch((error) => {
reject(error);
});
});
},
在store 的 permission.js 为动态路由的相关方法和存储
import { asyncRoutes, constantRoutes } from "@/router";
/**
* 通过meta中的roles信息判断用户是否有权限
* @param roles
* @param route
*/
function hasPermission(roles, route) {
if (route.meta && route.meta.roles) {
return roles.some((role) => route.meta.roles.includes(role));
} else {
return true;
}
}
/**
* 根据角色和配置生成当前用户的路由
* @param {array} routes 配置的路由
* @param {array} roles 用户角色
*/
let GenerateRoutes = (routes, roles) => {
let res = [];
routes.forEach((route) => {
const tmp = { ...route };
if (hasPermission(roles, tmp)) {
if (tmp.children) {
tmp.children = GenerateRoutes(tmp.children, roles);
}
// console.log(tmp);
res.push(tmp);
}
});
return res;
};
const getDefaultState = () => {
return {
roles: [],
routes: constantRoutes, // 用于配置页面导航等
};
};
const state = getDefaultState();
const mutations = {
SET_ROLES: (state, roles) => {
state.roles = roles;
},
SET_ROUTES: (state, routes) => {
state.routes = routes;
},
};
const actions = {
/**根据角色获取路由配置 */
getAsyncRoutes({ commit }, roles) {
let filterRoutes = GenerateRoutes(asyncRoutes, roles);
let res = constantRoutes.concat(filterRoutes);
commit("SET_ROUTES", res);
return res;
},
};
export default {
namespaced: true,
state,
mutations,
actions,
};
将新增的js文件引入store的index.js文件中
import Vue from "vue";
import Vuex from "vuex";
import getters from "./getters";
import app from "./modules/app";
import settings from "./modules/settings";
import user from "./modules/user";
import permission from "./modules/permission";
Vue.use(Vuex);
const store = new Vuex.Store({
modules: {
app,
settings,
user,
permission,
},
getters,
});
export default store;
路由文件
import Vue from "vue";
import Router from "vue-router";
Vue.use(Router);
/* Layout */
import Layout from "@/layout";
// 默认路由
export const constantRoutes = [
{
path: "/login",
component: () => import("@/views/login/index"),
hidden: true,
},
{
path: "/404",
component: () => import("@/views/404"),
hidden: true,
},
];
// 自定义动态路由,在meta中添加了roles,通过roles中是角色进行动态生成不同角色的动态路由
export const asyncRoutes = [
{
path: "/",
component: Layout,
redirect: "/employee",
meta: { roles: ["ROLE_ADMIN"] },
children: [
{
path: "employee",
name: "Employee",
component: () => import("@/views/employee/index"),
// meta: { title: "员工管理", icon: "el-icon-s-custom" },
meta: {
roles: ["ROLE_ADMIN"],
title: "员工管理",
icon: "el-icon-s-custom",
},
},
],
},
{
path: "/user",
component: Layout,
meta: { roles: ["ROLE_DEPT", "ROLE_EMP"] },
children: [
{
path: "user",
name: "User",
component: () => import("@/views/user/index"),
meta: {
roles: ["ROLE_DEPT", "ROLE_EMP"],
title: "个人信息",
icon: "el-icon-setting",
},
},
],
},
// 404 page must be placed at the end !!!
{ path: "*", redirect: "/404", 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;
此时登录成功并获取到用户信息后,可在控制台看到存储到store中的信息
登录成功界面实例
管理员
部门经理
文章来源:https://www.toymoban.com/news/detail-518902.html
基本员工文章来源地址https://www.toymoban.com/news/detail-518902.html
到了这里,关于Vue+Element UI 权限管理(角色 )的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!