路由权限的分类与踩坑记录

路由权限的分类与踩坑记录

路由的权限控制基本上分为两种,一种是完全由后端进行控制与分配权限,第二种是前端进行权限设置然后发送给后端,然后每次在登陆的时候调用这个路由权限的数组接口,根据这个接口的路由与基础路由进行合并。

1.后端进行控制与分配

在前端设置路由的时候,根据路由中是否有logIn_marking来判断是否需要需要进行权限判定,

css 复制代码
{
            path: 'router-face-swap-template',
            name: 'faceSwapV2',
            meta: {
                title: '',
                login_marking: 'faceSwapV2',
                showName: '图片换脸V2'
            },
            component: (resolve) => import('./views/ai-face/face-swap-template/index.vue'),
        }

如果有这个参数,则需要判定该用户是否有这个路由的权限,如果没有这个参数,则代表是常态路由,不需要进行判定,实现的时候用的是路由守卫的方式,将login_marking传到登录的仓库当中,进行islogin的判定

javascript 复制代码
router.beforeEach((to, from, next) => {
    // 拦截没有权限是路由
    ViewUI.LoadingBar.start();
    Util.title(to.meta.title);
    if (to.meta.login_marking) {
        if (!useUserStore(pinia).isLogin(to.meta.login_marking)) {
            console.log('need login')
            next({
                path: `router-login?redirect=${to.name}`,
                replace: true
            })
            return
        }
        console.log('LOGINED')
    }
    next();
});

router.afterEach((to, from, next) => {
    ViewUI.LoadingBar.finish();
    window.scrollTo(0, 0);
});

store中存储了登录信息和计算属性getters,将点击某个路由的login_marking传入到计算属性当中,进行判定,由于是数组数字,所以要加上映射,如果点击的路由在用户数组内,则代表该用户有这个权限。如果用户中没有则重定向到登录页面

javascript 复制代码
    state: () => {
        return {
            menus: [],
            roles: [],
            id: null,
            name: '',
            currentMenu: null,
        }
    },
    getters: {
        isLogin(state) {
            return (mark) => state.roles.includes(menuMap[mark])
        }
    },
arduino 复制代码
// 菜单权限map

export const menuMap = {
    aiFaceFusion: '9',
    aiFaceReplace: '8',
    aiFaceEmotion: '7',
    aigcConfig: '10',
    aigcMultiTest: '11',
    firstDayMail: '12',
    faceSwapV2: '13',
    aiLivePortrait: '14',
    aliemo: '15',
    vidu: '16',
}

2.前端端进行控制与分配

前端进行异步权限的设置会生成一个数组,根据接口传递给后端存储,每次登录的时候采用store中得到路由信息,由于是树状结构,因此采用递归的方法进行数组过滤,过滤出需要的数组路由,

typescript 复制代码
const filterAsyncRoute = (asyncRoute: any, routes: any) => {
  return asyncRoute.filter((item: any) => {
    if (routes.includes(item.name)) {
      if (item.children && item.children.length) {
        item.children = filterAsyncRoute(item.children, routes)
      }
      return true
    }
  })
}

然后将常态路由和遍历出的异步路由进行拼接,得到所有的路由,然后赋值给用户

typescript 复制代码
 // 获取用户信息
    async userInfo() {
      const result: userInfoResponseData = await reqUserInfo()
      if (result.code === 200) {
        this.username = result.data.name
        this.avatar = result.data.avatar
        const userAsyncRoute = filterAsyncRoute(
          cloneDeep(asyncRoute),
          result.data.routes,
        )
        const arr = [...userAsyncRoute, ...anyRoute]
        this.menuRoutes = [...constantRoute, ...arr]
        arr.forEach((item: any) => {
          router.addRoute(item)
        })
        return 'ok'
      } else {
        return Promise.reject(new Error(result.message))
      }
    },

踩坑记录1:跳转页面后404

当改变地址栏或者刷新页面的时候,页面会跳转到404,这是由于路由没有找到强匹配的地址,就会跳转到404页面

javascript 复制代码
    {
      path: '/404',
      name: '404',
      component: () => import('@/views/404'),
      hidden: true
    },
    {
      path: '*',
      redirect: '/404',
      hidden: true
    }

不在初始化路由的时候初始化,而是在解析接收的路由数据时拼接路由

javascript 复制代码
// 将生成数组树结构的菜单并拼接404路由
  const routes = Object.values(menusMap).concat(notFoundRoutes)

踩坑记录2:数据无法持久化

刷新页面会发现页面变空白,这是由于刷新页面router实例会重新初始化到初始状态,因此需要使用sessionstorage进行数据持久化

arduino 复制代码
export const useUserStore = defineStore('useUserStore', {
    // 开启数据缓存
    persist: {
        storage: sessionStorage,
    },
相关推荐
用户214118326360221 分钟前
首发!即梦 4.0 接口开发全攻略:AI 辅助零代码实现,开源 + Docker 部署,小白也能上手
前端
gnip2 小时前
链式调用和延迟执行
前端·javascript
SoaringHeart2 小时前
Flutter组件封装:页面点击事件拦截
前端·flutter
杨天天.2 小时前
小程序原生实现音频播放器,下一首上一首切换,拖动进度条等功能
前端·javascript·小程序·音视频
Dragon Wu3 小时前
React state在setInterval里未获取最新值的问题
前端·javascript·react.js·前端框架
Jinuss3 小时前
Vue3源码reactivity响应式篇之watch实现
前端·vue3
YU大宗师3 小时前
React面试题
前端·javascript·react.js
木兮xg3 小时前
react基础篇
前端·react.js·前端框架
ssshooter3 小时前
你知道怎么用 pnpm 临时给某个库打补丁吗?
前端·面试·npm
IT利刃出鞘4 小时前
HTML--最简的二级菜单页面
前端·html