上一篇文章中有同学提到路由鉴权,由于时间关系没有写,本文将针对这一特性对 vue 和 react 做专门说明,希望同学看了以后能够受益匪浅,对你的项目能够有所帮助,本文借鉴了很多大佬的文章篇幅也是比较长的。
背景单独项目中是希望根据登录人来看下这个人是不是有权限进入当前页面。虽然服务端做了进行接口的权限,但是每一个路由加载的时候都要去请求这个接口太浪费了。有时候是通过SESSIONID来校验登陆权限的。
在正式开始 react 路由鉴权之前我们先看一下vue的路由鉴权是如何工作的:
一、vue之beforeEach路由鉴权一般我们会相应的把路由表角色菜单配置在后端,当用户未通过页面菜单,直接从地址栏访问非权限范围内的url时,拦截用户访问并重定向到首页。
vue 的初期是可以通过动态路由的方式,按照权限加载对应的路由表 AddRouter ,但是由于权限交叉,导致权限路由表要做判断结合,想想还是挺麻烦的,所以采用的是在 beforeEach 里面直判断用非动态路由的方式
在使用 Vue的时候,框架提供了路由守卫功能,用来在进入某个路有前进行一些校验工作,如果校验失败,就跳转到 404 或者登陆页面,比如 Vue 中的 beforeEnter 函数:
... router.beforeEach(async(to, from, next) => { const toPath = to.path; const fromPath = from.path; }) ...
1、路由概览
// index.js import Vue from 'vue' import Router from 'vue-router' import LabelMarket from './modules/label-market' import PersonalCenter from './modules/personal-center' import SystemSetting from './modules/system-setting' import API from '@/utils/api' Vue.use(Router) const routes = [ { path: '/label', component: () => import(/* webpackChunkName: "index" */ '@/views/index.vue'), redirect: { name: 'LabelMarket' }, children: [ { // 基础公共页面 path: 'label-market', name: 'LabelMarket', component: () => import(/* webpackChunkName: "label-market" */ '@/components/page-layout/OneColLayout.vue'), redirect: { name: 'LabelMarketIndex' }, children: LabelMarket }, { // 个人中心 path: 'personal-center', name: 'PersonalCenter', redirect: '/label/personal-center/my-apply', component: () => import(/* webpackChunkName: "personal-center" */ '@/components/page-layout/TwoColLayout.vue'), children: PersonalCenter }, { // 系统设置 path: 'system-setting', name: 'SystemSetting', redirect: '/label/system-setting/theme', component: () => import(/* webpackChunkName: "system-setting" */ '@/components/page-layout/TwoColLayout.vue'), children: SystemSetting }] }, { path: '*', redirect: '/label' } ] const router = new Router({ mode: 'history', routes }) // personal-center.js export default [ ... { // 我的审批 path: 'my-approve', name: 'PersonalCenterMyApprove', component: () => import(/* webpackChunkName: "personal-center" */ '@/views/personal-center/index.vue'), children: [ { // 数据服务审批 path: 'api', name: 'PersonalCenterMyApproveApi', meta: { requireAuth: true, authRole: 'dataServiceAdmin' }, component: () => import(/* webpackChunkName: "personal-center" */ '@/views/personal-center/api-approve/index.vue') }, ... ] } ]
export default [ ... { // 数据服务设置 path: 'api', name: 'SystemSettingApi', meta: { requireAuth: true, authRole: 'dataServiceAdmin' }, component: () => import(/* webpackChunkName: "system-setting" */ '@/views/system-setting/api/index.vue') }, { // 主题设置 path: 'theme', name: 'SystemSettingTheme', meta: { requireAuth: true, authRole: 'topicAdmin' }, component: () => import(/* webpackChunkName: "system-setting" */ '@/views/system-setting/theme/index.vue') }, ... ]
2、鉴权判断
用户登陆信息请求后端接口,返回菜单、权限、版权信息等公共信息,存入vuex。此处用到权限字段如下:
_userInfo: { admin:false, // 是否超级管理员 dataServiceAdmin:true, // 是否数据服务管理员 topicAdmin:false // 是否主题管理员 }
判断当前路由是否需要鉴权(router中meta字段下requireAuth是否为true),让公共页面直接放行;
判断角色是超级管理员,直接放行;
(本系统特殊逻辑)判断跳转路径是主题设置但角色不为主题管理员,继续判断角色是否为数据服务管理员,跳转数据服务设置页or重定向(‘系统设置'菜单'/label/system-setting'默认重定向到'/label/system-setting/theme',其他菜单默认重定向的都是基础公共页面,故需要对这里的重定向鉴权。系统设置的权限不是主题管理员就一定是数据服务管理员,所以能这样做);
判断路由需求权限是否符合,若不符合直接重定向。