zoukankan      html  css  js  c++  java
  • vue+elementui搭建后台管理界面(6登录和菜单权限控制)

    不同的权限对应不同的路由(菜单),同时侧边栏也根据权限异步生成,实现登录和鉴权思路如下:

    • 登录:点击登录,服务器验证通过后返回一个 token ,然后存到 cookie,再根据 token 拉取用户权限
    • 鉴权:通过 token 获取对应的roles, 计算有权限的路由,使用 router.addRoutes 动态加载路由

    数据和操作通过 vuex 进行控制

    1 登录

    登录按钮 click 事件触发登录动作:

    /** ...省略的代码 */
    this.$store.dispatch('LoginByUsername', {
        'username': username, 'password': password
    })
    .then(() => {
        this.logining = false
        this.$notify.success({
        message: '欢迎登录',
        duration: 3 * 1000,
        })
        // 重定向到首页
        this.$router.push({ path: this.redirect || '/' })
    })
    .catch(err => {
        this.logining = false
        this.$alert(err, {
            type: 'warning',
            confirmButtonText: 'ok'
        })
    })
    /** ...省略的代码 */
    

    action:

    // 登入
    LoginByUsername({commit }, userInfo){
        const username = userInfo.username.trim()
        return new Promise((resolve, reject) => {
            loginByUsernameApi(username, userInfo.password)
            .then(response=> {
                const data = response.data
                setToken(data.token) // 储存token
                commit('SET_TOKEN', data.token)
                commit('SET_ACCOUNT', username)
                resolve()
            })
            .catch(err => {
                reject(err)
            })
        })
    }
    /** ...省略的代码 */
    

    登录成功,服务端返回一个token,然后储存到本地 cookie。

    2 获取用户权限

    对每个路由,在全局钩子 router.beforeEach 中拦截,判断是否已获取token,之后再获取用户的基本信息

    /** ...省略的代码 */
    if(store.getters.token) {
        // 判断当前用户是否已拉取完user_info信息
        if(store.getters.roles.length === 0){
            // 拉取用户信息
            store.dispatch('GetUserInfo').then(resp => {
                const roles = resp.data.roles
                next()
                /** ...省略的代码 */
                })
            })
        }
    }
    /** ...省略的代码 */
    

    action:

    // 获取用户信息, 名称、头像、权限
    GetUserInfo({commit, state}) {
        return new Promise((resolve, reject) => {
            getLoginUserInfoApi(state.token)
            .then(response => {
                if(!response.data){
                    reject('error')
                }
                const data = response.data
                const roles = data.data
                if(roles && roles.length > 0){
                    commit('SET_ROLES', roles)
                }else {
                    reject()
                }
    
                if(data.name){
                    commit('SET_NAME', data.name)
                }
    
                if(data.avatar){
                    commit('SET_AVATAR', data.avatar)
                }
    
                response.data.roles = roles
                resolve(response)
            })
            .catch(err => {
                reject(err)
            })
        })
    },
    

    3 菜单权限

    前端保存一份路由表,记录每一个路由和需要的权限。
    再根据用户信息里的 roles 计算对应的权限,然后生成有权限的菜单,再挂载路由。
    但这只是页面控制,后端也要相应的做权限验证。

    • 创建vue实例时使用vue-router挂载登录和一些公用页面,如首页、图表等
    • 用户登录后,将获取的roles和路由表的权限比较,生成用户可访问的路由表
    • 调用router.addRoutes添加可访问的路由
    • 使用vuex管理路由表,生成侧边栏菜单

    首先是 router.js 路由表

    import Vue from 'vue'
    import Router from 'vue-router'
    import Container from '@/containers/Container'
    import Login from '@/views/login'
    import Page404 from '@/views/404'
    import Dashboard from '@/views/dashboard'
    
    /** router modules */
    import systemRouter from './modules/system'
    
    Vue.use(Router)
    
    export const constantRouterMap = [
      {
        path: '/login',
        hidden: true,
        component: Login
      },
      {
        path: '/404',
        hidden: true,
        component: Page404
      },
      {
        path: '/',
        redirect: '/dashboard',
        component: Container,
        name: '首页',
        hidden: false,
        meta: { title: '首页', icon: '', noCache: true },
        children: [
          {
            path: 'dashboard',
            name: 'Dashboard',
            component: Dashboard,
            meta: { title: '首页', icon: 'fa fa-dashboard fa-lg', noCache: true }
          },
          {
            path: 'table',
            name: '表格综合实例',
            component: Form,
            meta: { title: '表格综合实例', icon: '', noCache: true }
          },
          // { path: '*', redirect: '/404', hidden: true }
        ]
      },
    ]
    
    export default new Router({
      mode: 'hash',
      scrollBehavior: () => ({ y: 0 }),
      routes: constantRouterMap
    })
    
    export const asyncRouterMap = [
      /** 其他的异步路由表 */
      systemRouter,
      { path: '*', redirect: '/404', hidden: true }
    ]
    

    同级目录下的 ./modules/system.js 路由表

    import Container from '@/containers/Container'
    /**
     * 系统管理相关路由
     */
    const systemRouter = {
      path: '/system',
      component: Container,
      redirect: '/system/permit/account',
      name: '系统管理',
      meta: {
        title: '系统管理',
        roles: ['/system']
      },
      children: [
        {
          path: 'permit',
          name: '权限管理',
          hidden: false, 
          redirect: '/system/permit/account',
          component: () => import('@/views/system/permit'),
          meta: { 
            title: '权限管理', 
            icon: 'fa fa-cog fa-lg',
            roles: ['/system/permit']  
          },
          children: [
            { path: 'account', name: '用户', 
              component: () => import('@/views/system/permit/account'), 
              meta: { title: '用户', icon: 'form', roles: ['/system/permit/account'] } 
            },
            { path: 'accountgroup', name: '用户组',  
              component: () => import('@/views/system/permit/accountgroup'), 
              meta: { title: '用户组', icon: 'form', roles: ['/system/permit/accountgroup'] } 
            },
            { path: 'role', name: '角色', 
              component: () => import('@/views/system/permit/role'),
               meta: { title: '角色', icon: 'form', roles: ['/system/permit/role'] } 
            },
            { path: 'authorize', name: '授权', 
              component: () => import('@/views/system/permit/authorize'),
               meta: { title: '授权', icon: 'form', roles: ['/system/permit/authorize'] } 
            },
          ]
        },
            
      ],
    }
    
    export default systemRouter
    

    roles: ['/system/permit/account'] 表示该页面需要的权限是 '/system/permit/account' 后端返回的 roles 里有这个记录则能访问对应的页面
    而 '/system/permit/account' 是 '/system/permit' 的子路由,所以要访问 '/system/permit/account',后端返回:

    roles: ['/system', '/system/permit', '/system/permit/account']

    注意: 404页面要最后加载,如果放在 constantRouterMap 中,所有后面的页面都会被拦截到404

  • 相关阅读:
    3、Spring Cloud Rest工程创建(通过IDEA创建)
    Centos7配置阿里epel源|yum源
    OSI七层模型:TCP/IP && HTTP && WebSocket && MQTT
    几种进程间的通信方式
    Tomcat类加载机制
    JAVA类加载器
    Spring事务隔离级别
    Spring事务传播特性
    Spring事务实现原理
    RPC框架Dubbo分析
  • 原文地址:https://www.cnblogs.com/wbjxxzx/p/10075077.html
Copyright © 2011-2022 走看看