当前位置:   article > 正文

Vue+Element UI 权限管理(角色 )_elementui框架根据角色roles回显相关页面

elementui框架根据角色roles回显相关页面

用户前台登录后,后台返回一个token,将该token存储到store中,并设置到header中,每次发起请求时都会携带该token,用于后台进行权限校验

  1. // 登录方法 login.vue
  2. handleLogin() {
  3. this.$refs.loginForm.validate((valid) => {
  4. if (valid) {
  5. this.loading = true;
  6. this.$store
  7. .dispatch("user/login", this.loginForm)
  8. .then(() => {
  9. this.$router.push({ path: this.redirect || "/" });
  10. this.loading = false;
  11. })
  12. .catch(() => {
  13. this.loading = false;
  14. });
  15. } else {
  16. console.log("error submit!!");
  17. return false;
  18. }
  19. });
  20. },

在store 的user.js中定义了该方法

  1. login({ commit }, userInfo) {
  2. const { userName, userPassword } = userInfo;
  3. return new Promise((resolve, reject) => {
  4. login({ userName: userName.trim(), userPassword: userPassword })
  5. .then((response) => {
  6. const { data } = response;
  7. commit("SET_TOKEN", data.token);
  8. setToken(data.token);
  9. resolve();
  10. })
  11. .catch((error) => {
  12. reject(error);
  13. });
  14. });
  15. },
  1. const mutations = {
  2. RESET_STATE: (state) => {
  3. Object.assign(state, getDefaultState());
  4. },
  5. SET_TOKEN: (state, token) => {
  6. state.token = token;
  7. },
  8. SET_NAME: (state, name) => {
  9. state.name = name;
  10. },
  11. SET_AVATAR: (state, avatar) => {
  12. state.avatar = avatar;
  13. },
  14. SET_AUTHORITIES: (state, authorities) => {
  15. state.authorities = authorities;
  16. },
  17. };

此时登录成功后,后台将返回一个token

在请求拦截器中将token添加到请求头上,在响应拦截器中设置未登录状态访问时跳转到登录页面

  1. import axios from "axios";
  2. import { MessageBox, Message } from "element-ui";
  3. import store from "@/store";
  4. import { getToken, removeToken } from "@/utils/auth";
  5. import router from "@/router";
  6. // create an axios instance
  7. const service = axios.create({
  8. baseURL: "http://localhost:8080", // url = base url + request url
  9. timeout: 5000, // request timeout
  10. });
  11. // request interceptor
  12. service.interceptors.request.use(
  13. (config) => {
  14. if (store.getters.token) {
  15. config.headers["token"] = getToken();
  16. }
  17. return config;
  18. },
  19. (error) => {
  20. console.log(error);
  21. return Promise.reject(error);
  22. }
  23. );
  24. // response 拦截器
  25. service.interceptors.response.use(
  26. (response) => {
  27. const res = response.data;
  28. // if the custom code is not 20000, it is judged as an error.
  29. if (res.code !== 200 && res.code !== 201) {
  30. Message({
  31. message: res.message || "Error",
  32. type: "error",
  33. duration: 5 * 1000,
  34. });
  35. // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
  36. if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
  37. // to re-login
  38. MessageBox.confirm(
  39. "You have been logged out, you can cancel to stay on this page, or log in again",
  40. "Confirm logout",
  41. {
  42. confirmButtonText: "Re-Login",
  43. cancelButtonText: "Cancel",
  44. type: "warning",
  45. }
  46. ).then(() => {
  47. store.dispatch("user/resetToken").then(() => {
  48. location.reload();
  49. });
  50. });
  51. }
  52. if (res.code == 401) {
  53. removeToken();
  54. router.replace({
  55. path: "/login",
  56. });
  57. }
  58. return Promise.reject(new Error(res.message || "Error"));
  59. } else {
  60. return res;
  61. }
  62. },
  63. (error) => {
  64. console.log("err" + error); // for debug
  65. Message({
  66. message: error.message,
  67. type: "error",
  68. duration: 5 * 1000,
  69. });
  70. return Promise.reject(error);
  71. }
  72. );
  73. export default service;

 在permission.js 中进行相关代码编写 (获取用户的信息,动态路由的生成加载)

 router.beforeEach()路由拦截()

  1. import router from "./router";
  2. import store from "./store";
  3. import { Message } from "element-ui";
  4. import NProgress from "nprogress"; // progress bar
  5. import "nprogress/nprogress.css"; // progress bar style
  6. import { getToken } from "@/utils/auth"; // get token from cookie
  7. import getPageTitle from "@/utils/get-page-title";
  8. NProgress.configure({ showSpinner: false }); // NProgress Configuration
  9. const whiteList = ["/login"]; // no redirect whitelist
  10. router.beforeEach(async (to, from, next) => {
  11. // start progress bar
  12. NProgress.start();
  13. // set page title
  14. document.title = getPageTitle(to.meta.title);
  15. // determine whether the user has logged in
  16. const hasToken = getToken();
  17. const hasRoles =
  18. store.state.user.authorities && store.state.user.authorities.length > 0;
  19. // 如果有token再跳转到登录页面时,根据获取的角色信息进行页面跳转
  20. if (hasToken) {
  21. if (to.path === "/login") {
  22. if (store.state.user.authorities) {
  23. if (store.state.user.authorities.includes("ROLE_ADMIN")) {
  24. next({ path: "/" });
  25. } else {
  26. next({ path: "/user" });
  27. }
  28. } else {
  29. next({ path: "/" });
  30. }
  31. NProgress.done();
  32. } else {
  33. // 获取登录用户名 如果用户名存在说明用户已经登录且获得了用户信息,直接放行,如果没有用户名,就进行用户信息获取
  34. const hasGetUserInfo = store.getters.name;
  35. if (hasGetUserInfo) {
  36. next();
  37. } else {
  38. try {
  39. //判断用户角色是否存在
  40. if (!hasRoles) {
  41. let userInfo = await store.dispatch("user/getInfo"); // 获取用户信息
  42. // 根据获得到的用户信息,获取用户角色信息并动态生成路由
  43. let routes = await store.dispatch(
  44. "permission/getAsyncRoutes",
  45. userInfo.user.authorities
  46. );
  47. router.options.routes = routes;
  48. router.addRoutes(routes); // 将生成的动态路由添加到原先的路由中
  49. next({ ...to, replace: true }); // 保证路由已挂载
  50. // 根据用户角色进行登录后的首页面跳转
  51. if (store.state.user.authorities) {
  52. if (store.state.user.authorities.includes("ROLE_ADMIN")) {
  53. next({ path: "/" });
  54. } else {
  55. next({ path: "/user/user" });
  56. }
  57. }
  58. }
  59. } catch (error) {
  60. // remove token and go to login page to re-login
  61. await store.dispatch("user/resetToken");
  62. Message.error(error || "Has Error");
  63. next(`/login`);
  64. NProgress.done();
  65. }
  66. }
  67. }
  68. } else {
  69. /* has no token*/
  70. if (whiteList.indexOf(to.path) !== -1) {
  71. // in the free login whitelist, go directly
  72. next();
  73. } else {
  74. // other pages that do not have permission to access are redirected to the login page.
  75. next(`/login`);
  76. NProgress.done();
  77. }
  78. }
  79. });
  80. router.afterEach(() => {
  81. // finish progress bar
  82. NProgress.done();
  83. });

获取用信息的方法定义在store的user.js中

  1. // 获取用户信息
  2. getInfo({ commit, state }) {
  3. return new Promise((resolve, reject) => {
  4. getInfo()
  5. .then((response) => {
  6. const { data } = response;
  7. if (!data) {
  8. return reject("Verification failed, please Login again.");
  9. }
  10. const { username, authorities } = data.user;
  11. // 将用户名,和用户角色信息存储到store中
  12. commit("SET_NAME", username);
  13. commit("SET_AUTHORITIES", authorities);
  14. resolve(data);
  15. })
  16. .catch((error) => {
  17. reject(error);
  18. });
  19. });
  20. },

在store 的 permission.js 为动态路由的相关方法和存储 

  1. import { asyncRoutes, constantRoutes } from "@/router";
  2. /**
  3. * 通过meta中的roles信息判断用户是否有权限
  4. * @param roles
  5. * @param route
  6. */
  7. function hasPermission(roles, route) {
  8. if (route.meta && route.meta.roles) {
  9. return roles.some((role) => route.meta.roles.includes(role));
  10. } else {
  11. return true;
  12. }
  13. }
  14. /**
  15. * 根据角色和配置生成当前用户的路由
  16. * @param {array} routes 配置的路由
  17. * @param {array} roles 用户角色
  18. */
  19. let GenerateRoutes = (routes, roles) => {
  20. let res = [];
  21. routes.forEach((route) => {
  22. const tmp = { ...route };
  23. if (hasPermission(roles, tmp)) {
  24. if (tmp.children) {
  25. tmp.children = GenerateRoutes(tmp.children, roles);
  26. }
  27. // console.log(tmp);
  28. res.push(tmp);
  29. }
  30. });
  31. return res;
  32. };
  33. const getDefaultState = () => {
  34. return {
  35. roles: [],
  36. routes: constantRoutes, // 用于配置页面导航等
  37. };
  38. };
  39. const state = getDefaultState();
  40. const mutations = {
  41. SET_ROLES: (state, roles) => {
  42. state.roles = roles;
  43. },
  44. SET_ROUTES: (state, routes) => {
  45. state.routes = routes;
  46. },
  47. };
  48. const actions = {
  49. /**根据角色获取路由配置 */
  50. getAsyncRoutes({ commit }, roles) {
  51. let filterRoutes = GenerateRoutes(asyncRoutes, roles);
  52. let res = constantRoutes.concat(filterRoutes);
  53. commit("SET_ROUTES", res);
  54. return res;
  55. },
  56. };
  57. export default {
  58. namespaced: true,
  59. state,
  60. mutations,
  61. actions,
  62. };

将新增的js文件引入store的index.js文件中

  1. import Vue from "vue";
  2. import Vuex from "vuex";
  3. import getters from "./getters";
  4. import app from "./modules/app";
  5. import settings from "./modules/settings";
  6. import user from "./modules/user";
  7. import permission from "./modules/permission";
  8. Vue.use(Vuex);
  9. const store = new Vuex.Store({
  10. modules: {
  11. app,
  12. settings,
  13. user,
  14. permission,
  15. },
  16. getters,
  17. });
  18. export default store;

路由文件

  1. import Vue from "vue";
  2. import Router from "vue-router";
  3. Vue.use(Router);
  4. /* Layout */
  5. import Layout from "@/layout";
  6. // 默认路由
  7. export const constantRoutes = [
  8. {
  9. path: "/login",
  10. component: () => import("@/views/login/index"),
  11. hidden: true,
  12. },
  13. {
  14. path: "/404",
  15. component: () => import("@/views/404"),
  16. hidden: true,
  17. },
  18. ];
  19. // 自定义动态路由,在meta中添加了roles,通过roles中是角色进行动态生成不同角色的动态路由
  20. export const asyncRoutes = [
  21. {
  22. path: "/",
  23. component: Layout,
  24. redirect: "/employee",
  25. meta: { roles: ["ROLE_ADMIN"] },
  26. children: [
  27. {
  28. path: "employee",
  29. name: "Employee",
  30. component: () => import("@/views/employee/index"),
  31. // meta: { title: "员工管理", icon: "el-icon-s-custom" },
  32. meta: {
  33. roles: ["ROLE_ADMIN"],
  34. title: "员工管理",
  35. icon: "el-icon-s-custom",
  36. },
  37. },
  38. ],
  39. },
  40. {
  41. path: "/user",
  42. component: Layout,
  43. meta: { roles: ["ROLE_DEPT", "ROLE_EMP"] },
  44. children: [
  45. {
  46. path: "user",
  47. name: "User",
  48. component: () => import("@/views/user/index"),
  49. meta: {
  50. roles: ["ROLE_DEPT", "ROLE_EMP"],
  51. title: "个人信息",
  52. icon: "el-icon-setting",
  53. },
  54. },
  55. ],
  56. },
  57. // 404 page must be placed at the end !!!
  58. { path: "*", redirect: "/404", hidden: true },
  59. ];
  60. const createRouter = () =>
  61. new Router({
  62. // mode: 'history', // require service support
  63. scrollBehavior: () => ({ y: 0 }),
  64. routes: constantRoutes,
  65. });
  66. const router = createRouter();
  67. // Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
  68. export function resetRouter() {
  69. const newRouter = createRouter();
  70. router.matcher = newRouter.matcher; // reset router
  71. }
  72. export default router;

 此时登录成功并获取到用户信息后,可在控制台看到存储到store中的信息

 登录成功界面实例

管理员

部门经理

基本员工

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/903307
推荐阅读
相关标签
  

闽ICP备14008679号