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

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

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

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,
    },
相关推荐
小周同学:15 分钟前
vue将页面导出成word
前端·vue.js·word
阿杰在学习28 分钟前
基于OpenGL ES实现的Android人体热力图可视化库
android·前端·opengl
xfq28 分钟前
[ai] cline使用总结(包括mcp)
前端·后端·ai编程
weiran199928 分钟前
手把手的建站思路和dev-ops方案
前端·后端·架构
小刀飘逸34 分钟前
子元素 margin-top 导致父元素下移问题的分析与解决方案
前端
Evrytos37 分钟前
告别石器时代#2:ES6新数据类型
前端·javascript
Ody40 分钟前
大屏开发适配方案全面解析
前端
java1234_小锋41 分钟前
一周学会Flask3 Python Web开发-SQLAlchemy数据迁移migrate
开发语言·前端·python·flask·flask3
wordbaby41 分钟前
Vue3滚动轮播组件实现超标信息自动滚动
前端·vue.js
AndyGoWei43 分钟前
写一个带联想词的输入框,看这篇文章就够了
前端·javascript