zoukankan      html  css  js  c++  java
  • vue【路由导航守卫控制访问主页前先登录】--实现用户登录及token验证----以及使用NProgress

    参考:

    实现用户登录及token验证:

    https://blog.csdn.net/qzcrystal/article/details/106884810

    https://www.cnblogs.com/tt-ff/p/11736463.html

    NProgress使用参考:

    https://blog.csdn.net/wn1245343496/article/details/82151273

    官网:http://ricostacruz.com/nprogress/
    github:https://github.com/rstacruz/nprogress

     主要用到导航守卫:

    官网:https://router.vuejs.org/zh/guide/advanced/navigation-guards.html#%E5%85%A8%E5%B1%80%E5%89%8D%E7%BD%AE%E5%AE%88%E5%8D%AB

    与main.js同级的 permission.js:

    import router from './router';
    import store from './store';
    import NProgress from 'nprogress';
    import 'nprogress/nprogress.css';
    import { Message } from 'element-ui';
    import { getToken } from '@/utils/auth'; // 验权从cookie中获取
    import { getUserInfo } from '@/api/user';
    import { setTitle } from '@/utils/mUtils'; // 设置浏览器头部标题
    
    function hasPermission(roles, permissionRoles) {
      if (roles.indexOf('admin') >= 0) {
        return true;
      }
      if (!permissionRoles) {
        return true;
      }
      return roles.some(role => permissionRoles.indexOf(role) >= 0);
    }
    
    const whiteList = ['/login']; // 不重定向白名单
    
    router.beforeEach((to, from, next) => {
      NProgress.start();
      // 设置头部浏览器标题
      const browserHeaderTitle = to.meta.title;
      store.commit('SET_BROWSERHEADERTITLE', {
        browserHeaderTitle: browserHeaderTitle
      });
      // 点击登录时拿到了token,并存入了了cookie,保证页面刷新时,始终可以拿到token
      if (getToken('Token')) {
        if (to.path === '/login') {
          next();
          NProgress.done();
        } else {
          // 用户登录成功之后,每次点击路由都进行角色的判断
          if (store.getters.roles.length === 0) {
            const token = getToken('Token');
            getUserInfo({ token: token })
              .then(res => {
                console.log(res);
                const userList = res.data.userList;
                store.commit('SET_ROLES', userList.roles);
                store.commit('SET_NAME', userList.name);
                store.commit('SET_AVATAR', userList.avatar);
                store
                  .dispatch('GenerateRoutes', { roles: userList.roles })
                  .then(() => {
                    // 根据roles权限生成可访问的路由表
                    router.addRoutes(store.getters.addRouters); // 动态添加可访问权限路由表
                    next({ ...to, replace: true }); // hack方法,确保addRoutes已经完成
                  });
              })
              .catch(err => {
                store.dispatch('LogOut').then(() => {
                  Message.error(err || 'V;erification failed, please login again');
                  next({ path: '/login' });
                });
              });
          } else {
            // 没有动态改编权限的需求可直接next() 删除下方权限判断
            if (hasPermission(store.getters.roles, to.meta.roles)) {
              next();
            } else {
              next({ path: '/401', replace: true, query: { noGoBack: true } });
            }
          }
        }
      } else {
        if (whiteList.indexOf(to.path) !== -1) {
          // 点击退出时,会定位到这里
          next();
        } else {
          next('/login');
          NProgress.done();
        }
      }
    });
    
    router.afterEach(() => {
      NProgress.done();
      setTimeout(() => {
        const browserHeaderTitle = store.getters.browserHeaderTitle;
        setTitle(browserHeaderTitle);
      }, 0);
    });

    main.js:

    import '@/permission.js';

    路由:router:index.js

    import Vue from "vue";
    import Router from "vue-router";
    import { Layout, Content } from "../layout"; // 页面整体布局
    import { topRouterMap } from "./topRouter";
    
    process.env.NODE_ENV === "development" ? Vue.use(Router) : null;
    
    function filterTopRouterMap(name) {
      let router = topRouterMap.find((item) => {
        return item.parentName === name;
      });
      return router.data; // arr
    }
    
    /**
     * 1、roles:后台返回的权限结构;
     *
     */
    //手动跳转的页面白名单
    const whiteList = ["/"];
    /**
     * path:''与path:'*'的区别:
     * 1、path:'*', 会匹配所有路径
     * 2、path:'',也是会匹配到路由
     *
     */
    //默认不需要权限的页面
    export const constantRouterMap = [
      {
        path: "",
        component: Layout,
        redirect: "/index/index",
        hidden: true,
      },
      {
        path: "/login",
        name: "login",
        component: () => import("@/page/login"),
        hidden: true,
      },
      {
        path: "/404",
        component: () => import("@/page/errorPage/404"),
        hidden: true,
      },
      {
        path: "/401",
        component: () => import("@/page/errorPage/401"),
        hidden: true,
      },
      {
        path: "/index",
        name: "index",
        component: Layout,
        meta: {
          title: "首页",
          icon: "icondashboard",
        },
        noDropdown: true,
        children: [
          {
            path: "index",
            meta: {
              title: "首页",
              icon: "icondashboard",
              routerType: "leftmenu",
            },
            component: () => import("@/page/index/index"),
          },
        ],
      },
    ];
    
    //注册路由
    export default new Router({
      mode: "history", // 默认为'hash'模式
      base: "/permission/", // 添加跟目录,对应服务器部署子目录
      routes: constantRouterMap,
    });
    
    //异步路由(需要权限的页面)
    export const asyncRouterMap = [
      {
        path: "/userManager",
        name: "userManage",
        component: Layout,
        meta: {
          title: "用户管理",
          icon: "iconuser",
        },
        noDropdown: true,
        children: [
          {
            path: "userList",
            meta: {
              title: "用户管理",
              icon: "iconuser",
              routerType: "leftMenu",
            },
            component: () => import("@/page/userList/userList"),
          },
        ],
      },
      {
        path: "/share",
        name: "share",
        component: Layout,
        meta: {
          title: "分享功能",
          icon: "iconshare",
        },
        noDropdown: true,
        children: [
          {
            path: "share",
            meta: {
              title: "分享功能",
              icon: "iconshare",
              routerType: "leftMenu",
            },
            component: () => import("@/page/share"),
          },
        ],
      },
      {
        path: "/infoManage",
        name: "infoManage",
        meta: {
          title: "信息管理",
          icon: "iconinfo",
        },
        component: Layout,
        children: [
          {
            path: "infoShow",
            name: "infoShow",
            meta: {
              title: "个人信息",
              icon: "iconinfo",
              routerType: "leftMenu",
              titleList: [
                { path: "infoShow1", title: "个人信息子菜单1" },
                { path: "infoShow2", title: "个人信息子菜单2" },
                { path: "infoShow3", title: "个人信息子菜单3" },
                { path: "infoShow4", title: "个人信息子菜单4" },
                { path: "infoShow5", title: "个人信息子菜单5" },
              ],
            },
            component: Content,
            children: filterTopRouterMap("infoShow"),
          },
          {
            path: "infoModify",
            name: "infoModify",
            meta: {
              title: "修改信息",
              icon: "iconinfo",
              routerType: "leftmenu",
              titleList: [
                { path: "infoModify1", title: "修改信息子菜单1" },
                { path: "infoModify2", title: "修改信息子菜单2" },
                { path: "infoModify3", title: "修改信息子菜单3" },
              ],
            },
            component: Content,
            children: filterTopRouterMap("infoModify"),
          },
        ],
      },
      {
        path: "/fundManage",
        name: "fundManage",
        meta: {
          title: "资金管理",
          icon: "iconpay3",
        },
        component: Layout,
        children: [
          {
            path: "fundList",
            name: "fundList",
            meta: {
              title: "资金流水",
              routerType: "leftmenu",
            },
            component: () => import("@/page/fundList/fundList"),
          },
          {
            path: "chinaTabsList",
            name: "chinaTabsList",
            meta: {
              title: "区域投资",
              routerType: "leftmenu",
            },
            component: () => import("@/page/fundList/chinaTabsList"),
          },
        ],
      },
      {
        path: "/fundData",
        name: "fundData",
        meta: {
          title: "资金数据",
          icon: "iconecharts",
        },
        component: Layout,
        redirect: "/fundData/fundPosition",
        children: [
          {
            path: "fundPosition",
            name: "fundPosition",
            meta: {
              title: "投资分布",
            },
            component: () => import("@/page/fundData/fundPosition"),
          },
          {
            path: "typePosition",
            name: "typePosition",
            meta: {
              title: "项目分布",
            },
            component: () => import("@/page/fundData/typePosition"),
          },
          {
            path: "incomePayPosition",
            name: "incomePayPosition",
            meta: {
              title: "收支统计",
            },
            component: () => import("@/page/fundData/incomePayPosition"),
          },
        ],
      },
      {
        path: "/permission",
        name: "permission",
        meta: {
          title: "权限设置",
          icon: "iconpermission",
          roles: ["admin", "editor"], // you can set roles in root nav
        },
        component: Layout,
        redirect: "/permission/page",
        children: [
          {
            path: "page",
            name: "pagePer",
            meta: {
              title: "页面权限",
              roles: ["admin"], // or you can only set roles in sub nav
            },
            component: () => import("@/page/permission/page"),
          },
          {
            path: "directive",
            name: "directivePer",
            meta: {
              title: "按钮权限",
              roles: ["editor"],
            },
            component: () => import("@/page/permission/directive"),
          },
        ],
      },
      {
        path: "/error",
        component: Layout,
        name: "errorPage",
        meta: {
          title: "错误页面",
          icon: "iconError",
        },
        children: [
          {
            path: "401",
            name: "page401",
            component: () => import("@/page/errorPage/401"),
            meta: {
              title: "401",
              noCache: true,
            },
          },
          {
            path: "404",
            name: "page404",
            component: () => import("@/page/errorPage/404"),
            meta: {
              title: "404",
              noCache: true,
            },
          },
        ],
      },
      { path: "*", redirect: "/404", hidden: true },
    ];
    
    /**
     *  路由设置要求:
     * 1、该路由有子菜单,可以设置多层嵌套路由children;如果没有子菜单,不需要设置children;通过item.children.length来判断路由的级数;
     * 2、登录成功后,定位到系统首页时,需要加载页面整体布局组件Layout并进行子路由定向加载;
     *
     * 按需加载路由组件的2种方法:
     * 1、component: () => import('@/page/login')
     * 2、component:resolve => require(['@/page/fundPosition'], resolve)
     *
     *
     *
     * 什么情况下,路由会定位到404页面?
     * 路由中redirect:'',不起作用?
     * 三级子菜单要在顶部展示?
     *
     *
     *
     */

  • 相关阅读:
    MySQL数据库之WHERE条件语句
    MySQL数据库的简单操作指令之DML语言
    课程设计必备之数据库操作代码模板
    MySQL数据库之外键约束的简单理解
    pdf.js的使用
    javascript连连看
    数据库问题
    列表文字超出后,鼠标悬浮显示全部内容
    springboot component注入servecie
    点击列表 获取table tr td 下的input value
  • 原文地址:https://www.cnblogs.com/hahahakc/p/13253485.html
Copyright © 2011-2022 走看看