vue-element-admin 登陆及目录权限控制的实现

目录
  • 登陆
  • 目录权限

登陆

万事开头难,做什么事都要有个起点,后面才能更好的进行下去,因此我选择的起点就是最为直观的登陆页面 /login/index.vue

/src/views/login/index

去除那些无关的东西,比如什么 rules 校验啊,默认的账号密码之类的东西,直接看核心登陆方法 handleLogin

  handleLogin() {
      this.$refs.loginForm.validate(valid => {
        if (valid) {
          this.loading = true
          # 请求 store 中的方法
          this.$store.dispatch('LoginByUsername', this.loginForm).then(() => {
            this.loading = false
            this.$router.push({ path: this.redirect || '/' })
          }).catch((errorMsg) => {
            this.loading = false
            this.$message({
              type: 'error',
              message: errorMsg
            })
          })
        } else {
          console.log('error submit!!')
          return false
        }
      })
    },

store 主要事做一些缓存之类的处理,这里调用了 store 中的 LoginByUsername 把表单内容传过去,这里我就改了点 catch 把我自己需要的错误信息进行提示,其他东西不需要改动

/src/store/modules/user

上面登陆中请求的 LoginByUsername 正是在这

    // 用户名登录
    LoginByUsername({ commit }, userInfo) {
      const username = userInfo.username.trim()
      return new Promise((resolve, reject) => {
        // 请求后台登陆
        loginByUsername(username, userInfo.password).then(response => {
          const data = response.data
          if (response.data.errorCode !== 200) {
            // 登陆失败,回传提示信息
            reject(data.errorMsg)
          }
          // 设置 token,作为用户已登陆的前端标识,存在 cookie 中
          commit('SET_TOKEN', data.retData)
          setToken(data.retData)
          resolve()
        }).catch(error => {
          reject(error)
        })
      })
    },

setToken() 方法会把 token 保存到 cookie 里,很重要

下面有个 GetUserInfo 方法,在你登陆的时候会去获取你的权限数据

    // 获取用户信息
    GetUserInfo({ commit, state }) {
      return new Promise((resolve, reject) => {
        // 请求获取权限
        getUserInfo(state.token).then(response => {
          if (response.status !== 200) { // 由于mockjs 不支持自定义状态码只能这样hack
            reject('error')
          }
          const data = response.data

          if (data.retData.module && data.retData.module.length > 0) { // 验证返回的roles是否是一个非空数组
            commit('SET_ROLES', data.retData.module)
          } else {
            // 当用户无任何权限时设置
            commit('SET_ROLES', ['普通用户'])
          }

          commit('SET_NAME', data.retData.username)
          commit('SET_AVATAR', 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif')
          commit('SET_INTRODUCTION', data.retData.username)
          resolve(response)
        }).catch(error => {
          reject(error)
        })
      })
    },

不需要知道那个 new Promise 啥的干啥用,反正我不知道,只要知道 getUserInfo 这个方法就行了,这个方法会以上面之前保存的 token 为参数去请求获取你的用户权限,原逻辑是没有权限就跳登陆页面,我这系统需要,没权限也有个首页可看,所以
SET_ROLES 参数给了个“普通用户”,反正什么值无所谓有值,没权限就行。
下面 commit 里的参数,分别为,用户名,头像,介绍,保留就好,也可自定义。
PS:在每次页面跳转时候页面都会走一个 GetUserInfo ,以此来判断用户有没有失效,因此,我的做法是直接把用户信息包括权限保存在 redis 里取,不要每次都从库里查

/src/utils/request.js

此文件是请求与返回拦截器,我们看返回值拦截器

每次你请求从后台接口返回时,都会经过返回值拦截器,默认的逻辑是返回的 code 不为 20000 时候就会被拦截,这里需要我们改为自己的逻辑,很多人配置都对,点登录一直 error 就是因为这个原因

// response interceptor
service.interceptors.response.use(
  response => response,
  /**
   * 下面的注释为通过在response里,自定义code来标示请求状态
   * 当code返回如下情况则说明权限有问题,登出并返回到登录页
   * 如想通过 xmlhttprequest 来状态码标识 逻辑可写在下面error中
   * 以下代码均为样例,请结合自生需求加以修改,若不需要,则可删除
   */
  // response => {
  //   const res = response.data
  //   if (res.code !== 20000) {
  //     Message({
  //       message: res.message,
  //       type: 'error',
  //       duration: 5 * 1000
  //     })
  //     // 50008:非法的token; 50012:其他客户端登录了;  50014:Token 过期了;
  //     if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
  //       // 请自行在引入 MessageBox
  //       // import { Message, MessageBox } from 'element-ui'
  //       MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', {
  //         confirmButtonText: '重新登录',
  //         cancelButtonText: '取消',
  //         type: 'warning'
  //       }).then(() => {
  //         store.dispatch('FedLogOut').then(() => {
  //           location.reload() // 为了重新实例化vue-router对象 避免bug
  //         })
  //       })
  //     }
  //     return Promise.reject('error')
  //   } else {
  //     return response.data
  //   }
  // },
  error => {
    console.log('err' + error) // for debug
    Message({
      message: '连接异常',
      // message: error.message,
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(error)
  }
)

/src/api/login

接口的请求都会从这里去请求后台,就不多赘述,基本只需要改动下请求路径就ok了。
登出 logout 也是,请求保证后台注销,前端处理部分也是在 store/modules/user 里的 LogOut 方法,基本不需要改动。

目录权限

大多数系统都有根据用户权限,或者说角色,展示相应页面的要求

/src/router/index

结合框架来实现目录的控制,如果是传统项目,一般是把目录结构整个存在后台数据库里,然后前端循环展示出来,但是这个在这里不需要这么麻烦,只需要把每个页面对应的权限保存起来就行了

目录在分为两个部分 constantRouterMap 与 asyncRouterMap
constantRouterMap:主要是通用部分,每个用户都有的页面
asyncRouterMap:需要进行权限过滤的页面

所以像首页这种都丢在 constantRouterMap 里,而像权限管理页面这种放在 asyncRouterMap 里
在目录上加上 permission 标识,这个是我自定义的唯一标识,用于区分每个页面的权限,我这里直接以页面的路径为值,因为路径肯定唯一

  {
    path: '',
    component: Layout,
    alwaysShow: true,
    redirect: '/xxx/xxx',
    name: 'xxx',
    meta: {
      title: 'xxx',
      icon: 'xxx'
    },
    children: [
      {
        path: '/xxx/xxx',
        component: () => import('@/views/xxx/xxx'),
        name: 'xxx',
        meta: {
          title: 'xxx',
          icon: 'message',
          # 权限标识,每个目录唯一
          permission: '/xxx/xxx',
          noCache: false }
      }
    ]
  },

然后就只需要在加载目录时对目录进行判断就可以了

/src/permission

这个文件就是整个路由逻辑在这

从这里的逻辑可以看到,登陆后,现在判断了用户权限,如果没权限就会进入之前说到的 GetUserInfo 方法去获取权限,由于要对目录进行控制,所以在 GetUserInfo 里我们也需要获取到目录的权限列表,只需要获取到有的就行了,没有权限的目录就不需要获取。
在 GetUserInfo 的最后通过 resolve 方法把返回值返回这个页面,截图中  module 就是我获取到的有权限的目录列表,然后通过
GenerateRoutes 来生成要加载的目录,接下来就是改这了
PS:不少人加我 QQ,说不明白这里什么意思,以及不知道要怎样的目录数据,我做个简要的说明。从这个 permission 文件中我们可以看到目录渲染一共三步:
1. GetUserInfo 中获取到你的目录数据(我权限数据全放这个方法里获取了:用户数据,目录权限,数据权限等),但这里主要的就是目录权限
2.在上门这个 permission.js 目录渲染的逻辑中获取 GetUserInfo 中获取到的目录权限,也就是上面那句
const roles = res.data.retData.module 这个 module 就是我返回值中目录权限的部分,module 就是模块的意思
3.也就是下一步,在 GenerateRoutes 方法中把 roles 目录权限传进去进行目录渲染

然后目录权限的数据到底长什么样?先来看下表结构

我代码中拿到的数据:

我们要用的只有这个 permission 字段,说简单点,你既可以和我一样直接拿到目录对象的所有数据,也可以单单取这个 permission 字段组成的数组,看自己习惯,具体后面判断逻辑在下面目录渲染的部分,单单数组的逻辑会更加简单点

/src/store/modules/permission

找到 GenerateRoutes

const permission = {
  state: {
    routers: constantRouterMap,
    addRouters: []
  },
  mutations: {
    SET_ROUTERS: (state, routers) => {
      state.addRouters = routers
      state.routers = constantRouterMap.concat(routers)
    }
  },
  actions: {
    GenerateRoutes({ commit }, data) {
      return new Promise(resolve => {
        const { roles } = data
        // 权限对列表进行过滤
        const accessedRouters = filterAsyncRouter(asyncRouterMap, roles)
        commit('SET_ROUTERS', accessedRouters)
        resolve()
      })
    }
  }
}

对于通用目录我们不需要管,在原逻辑中,这里通过判断如果用户是管理员就直接把整个权限目录都加载,如果不是再进行过滤,因为我们这完全就通过后台控制,包括管理员所以就把判断去掉了,直接对目录进行过滤

找到 filterAsyncRouter 方法

/**
 * 递归过滤异步路由表,返回符合用户角色权限的路由表
 * @param routes asyncRouterMap
 * @param roles
 */
function filterAsyncRouter(routes, roles) {
  const res = []
  routes.forEach(route => {
    const tmp = { ...route }
    if (hasPermission(roles, tmp)) {
      // 是否存在子节点,存在子节点说明当前节点为展开栏,并非页面
      if (tmp.children) {
        tmp.children = filterAsyncRouter(tmp.children, roles)
        // forCheck() 方法递归判断该节点下是否存在页面,不存在则隐藏
        // true:不存在,false:存在
        tmp.hidden = forCheck(tmp.children)
      }
      res.push(tmp)
    }
  })

  return res
}

/**
 * 递归子节点,判断是否存在展示页面,存在返回 false,不存在返回 true
 * @param routes
 */
function forCheck(routes) {
  // 设置默认为隐藏
  let isHidden = true
  // 判断是否存页面,不存在说明该节点下不存在页面
  if (routes != null && routes.length > 0) {
    // 循环子目录,如果子目录中不存在需要权限页面
    // 说明子页面全是展开栏,隐藏
    for (const route of routes) {
      // 存在 permission 说明为页面,不存在说明为展开栏,将子页面列表继续递归
      if (route.meta && route.meta.permission) {
        isHidden = false
        return
      } else {
        isHidden = forCheck(route.children)
      }
    }
  }
  return isHidden
}

通过循环权限目录通过 hasPermission 方法进行判断
forCheck 是我自己封装的方法,因为项目中不只存在二级目录,所以,通过递归的方式,判断子节点下是否有展示页,也就是带 permission 的页面,如果有,返回 false,没有返回 true

/**
 * 通过meta.role判断是否与当前用户权限匹配
 * @param roles
 * @param route
 */
function hasPermission(roles, route) {
  if (route.meta && route.meta.permission) {
    return roles.some(role => route.meta.permission.includes(role.permission))
  } else {
    return true
  }
}

hasPermission 方法,这里,我们之前加的 permission 参数就起到作用了
如果有 permission 就进行判断, roles 参数就是 /src/permission 里传过来的 module 目录。
通过 roles.some 循环 roles 别名 role,如果目录里 includes(包含)这个目录权限,就返回true,否则 false,为 true 的会被显示,当然如果直接没有 permission 就说明不需要后台管控,就直接 true,这样目录就被加载出来了。

到此这篇关于vue-element-admin 登陆及目录权限控制的实现的文章就介绍到这了,更多相关vue-element-admin 登陆及目录权限控制内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 使用vue-element-admin框架从后端动态获取菜单功能的实现

    2.详解 ​整体思路为:登陆 > 成功后根据用户信息获取菜单 > 根据菜单生成路由信息 2.1.新增asyncRoutes路由 ​在vue-router路径src\router\index.js中新增asyncRoutes数组,用来存放后端获取的菜单对应的路由信息. export const asyncRoutes = [ { path: '*', redirect: '/404', hidden: true } ] constantRoutes和asyncRoutes的区别 constant

  • vue-element-admin搭建后台管理系统的实现步骤

    近期在搞一个会议健康申报系统时,要搞一个后台,用到了vue-element-admin模板,使用的是PanJianChen(源码地址:https://github.com/PanJiaChen/vue-admin-template) 第一步:当前是下载源码了,下载地址:https://github.com/PanJiaChen/vue-admin-template 第二步:修改登录页面,登录接口(/store/modules/admin.js/login()),根据实际情况修改用户信息接口(/s

  • vue-element-admin登录全流程分享

    目录 1.安装最新的vue-element-admin 2.如有需要可以去掉eslint 3.删除所有的eslint文件 4.开始安装依赖包 5.启动服务 6.进入登录页面 7.后端编写登录接口 8.如需验证码,对登录页面进行改造 9.(重点)进行登录请求 10.刚刚发送的登录请求就进入下面这个函数里面去 1.安装最新的vue-element-admin 2.如有需要可以去掉eslint 在下面这个文件里面全局搜索 3.删除所有的eslint文件 4.开始安装依赖包 npm install 5.

  • vue-element-admin项目导入和导出的实现

    vue-element-admin导入组件封装 模板和样式 首先封装一个类似的组件,首先需要注意的是,类似功能,vue-element-admin已经提供了,我们只需要改造即可 excel导入功能需要使用npm包xlsx,所以需要安装xlsx插件 npm i xlsx 将vue-element-admin提供的导入功能新建一个组件,位置: src/components/UploadExcel import CommonTools from './CommonTools' import Uploa

  • vue-element-admin 菜单标签失效的解决方式

    设置菜单路由时,代码如下: { path: '/materieluse', component: Layout, meta: { title: '仓库管理', icon: 'component' }, children: [{ path: 'materielList', component: () => import('@/views/materieluse/materielList'), name: 'icons', meta: { title: '请料管理' } }, { path: 'it

  • vue-element-admin如何设置默认语言

    目录 vue-element-admin设置语言 vue-element-admin使用常见问题 vue-element-admin添加快捷导航 去掉Mock使用真实数据. vue-element-admin设置语言 今天下了一个vue-element-admin框架来玩玩儿,下完之后发现默认语言是英文的,那可不行. 后来发现自己下错了,其实这个应该是这样的,如果要中文版,你要下载 i18n 分支的才行,地址是这个 i18n 分支 . 下载完之后然后还需要改一个地方,\src\lang\inde

  • vue-element-admin配置小结

    目录 1. 项目初始化 2. 项目精简 3. 项目配置 4. 项目结构分析 1. 项目初始化 git clone https://github.com/PanJiaChen/vue-element-admin cd vue-element-admin npm install npm run dev 2. 项目精简 删除scr/views下的源码, 保留: dashboard:首页 error-page:异常页面 login:登录 redirect:重定向 对src/router/index 进行

  • vue-element-admin 登陆及目录权限控制的实现

    目录 登陆 目录权限 登陆 万事开头难,做什么事都要有个起点,后面才能更好的进行下去,因此我选择的起点就是最为直观的登陆页面 /login/index.vue /src/views/login/index 去除那些无关的东西,比如什么 rules 校验啊,默认的账号密码之类的东西,直接看核心登陆方法 handleLogin handleLogin() { this.$refs.loginForm.validate(valid => { if (valid) { this.loading = tr

  • 基于Vue自定义指令实现按钮级权限控制思路详解

    思路: 登录:当用户填写完账号和密码后向服务端验证是否正确,验证通过之后,服务端会返回一个token,拿到token之后(我会将这个token存贮到sessionStorage中,保证刷新页面后能记住用户登录状态),前端会根据token再去拉取一个 user_info 的接口来获取用户的详细信息(如用户权限,用户名等等信息). 权限验证:通过token获取用户对应的 role,自定义指令,获取路由meta属性里btnPermissions( 注: meta.btnPermissions是存放按钮

  • Vue路由守卫及页面登录权限控制的设置方法(两种)

    ①先在我们的登录页面存储一个登录数据 // 登录成功时保存一个登录状态: sessionStorage.setItem("flag", 1); ② 添加路由守卫 方法一: 直接在路由中添加 const router = new VueRouter({ ... }) // 路由守卫 router.beforeEach((to, from, next) => { // ... }) 方法二:当我们使用的是export default 方法时可以在main.js中添加 router.b

  • 基于vue,vue-router, vuex及addRoutes进行权限控制问题

    基于vuex, vue-router,vuex的权限控制教程,完整代码地址见 https://github.com/linrunzheng/vue-permission-control 接下来让我们模拟一个普通用户打开网站的过程,一步一步的走完整个流程. 首先从打开本地的服务localhost:8080开始,我们知道打开后会进入login页面,那么判断的依据是什么. 首先是token. 没有登陆的用户是获取不到token的,而登陆后的角色我们会将token存到local或者seesionStor

  • Vue 页面权限控制和登陆验证功能的实例代码

    页面权限控制 页面权限控制是什么意思呢? 就是一个网站有不同的角色,比如管理员和普通用户,要求不同的角色能访问的页面是不一样的.如果一个页面,有角色越权访问,这时就得做出限制了. Vue 动态添加路由及生成菜单 这是我写过的一篇文章, 通过动态添加路由和菜单来做控制,不能访问的页面不添加到路由表里,这是其中一种办法. 另一种办法就是所有的页面都在路由表里,只是在访问的时候要判断一下角色权限.如果有权限就让访问,没有权限就拒绝,跳转到 404 页面. 思路: 在每一个路由的 meta 属性里,将能

  • Vue Element前端应用开发之功能点管理及权限控制

    目录 概述 1.权限功能点管理 2.VUE+Element 前端权限控制 概述 本篇随笔介绍功能点管理及权限控制,功能点是作为一个业务对象数据进行管理,在角色范畴上进行分配,而在界面元素控制上,VUE+Element 前端引入Vue自定义指令Directives进行控制. 1.权限功能点管理 我们在前面分析过一个权限系统的表和关系的说明,如下所示. 权限功能点的管理就是对TB_Function的表的管理操作,这个表是我们定义用于系统控制的功能点. 权限功能点的管理为了展示它的树状结果,包括树列表

  • Vue实现两种路由权限控制方式

    目录 方式一:路由元信息(meta) 方式二:动态生成路由表(addRoutes) 路由权限控制常用于后台管理系统中,对不同业务人员能够访问的页面进行一个权限的限制. 对于无权限的页面可以跳转404页面或者提示无权限. 方式一:路由元信息(meta) 把所有页面都放在路由表中,只需要在访问的时候判断一下角色权限即可. vue-router 在构建路由时提供了元信息 meta 配置接口,我们可以在元信息中添加路由对应的权限,然后在路由守卫中检查相关权限,控制其路由跳转. 在 meta 属性里,将能

  • 深入浅析Yii admin的权限控制

    说到CMS,最需要有的东西就是权限控制,特别是一些复杂的场景,多用户,多角色,多部门,子父级查看等等.最近在开发一个线下销售的东东,这个系统分为管理员端,省代端,客户端,门店端,销售端, 部门端,部门老大下面分子部门等等,恶心的需求.我们这个项目使用yii框架开发,yii在php届还是比较流行的,虽然说laravel现在横行,但是一些部门一些团队还是采用了yii框架,比如我们. 我是刚接触yii这个框架,开始的时候对这种面向组件的框架甚是别扭.当时打算自己写权限的,自己创建权限表,关联表等,但是

  • Vue 权限控制的两种方法(路由验证)

    下面介绍两种权限控制的方法: 路由元信息(meta) 动态加载菜单和路由(addRoutes) 路由元信息(meta) 如果一个网站有不同的角色,比如 管理员 和 普通用户 ,要求不同的角色能访问的页面是不一样的 这个时候我们就可以 把所有的页面都放在路由表里 ,只要 在访问的时候判断一下角色权限 .如果有权限就让访问,没有权限的话就拒绝访问,跳转到404页面 vue-router 在构建路由时提供了元信息 meta 配置接口,我们可以在元信息中添加路由对应的权限,然后在路由守卫中检查相关权限,

  • Vue路由权限控制解析

    前言 本人在公司主要负责中后台系统的开发,其中路由和权限校验算是非常重要且最为基本的一环.实际开发项目中,关于登录和路由权限的控制参照了vue-element-admin这个明星项目,并在此基础上基于业务进行了整合,接下来我会以这个项目为例,仔细地剖析整个路由和权限校验的过程,也算是对这个知识点的一些总结. 项目总体目录结构 进入今天主题之前,我们先来梳理下整个项目,src目录下的. api: 接口请求 assets: 静态资源 components: 通用组件 directive: 自定义指令

随机推荐