Comment Vue implémente la gestion des autorités (routage dynamique addRoutes)

Table des matières

introduction

Recommander la vidéo de la station B

1. Gestion des pouvoirs

2. Autorité de contrôle

Autorisations d'interface

Contrôle de l'autorité de routage

première méthode

Deuxième méthode

autorisations de menu

première méthode

Deuxième méthode

autorisations des boutons

première méthode

Deuxième méthode


introduction

Dans le projet, il y aura une gestion des autorisations pour permettre à des utilisateurs spécifiques d'avoir des autorisations spécifiques. Alors, comment faire cette gestion des autorisations et combien de méthodes existe-t-il ? Laissez-moi vous en parler

Recommander la vidéo de la station B

Gestion des autorisations Vue (exemple)_哔哩哔哩_bilibili

Gestion des autorisations Vue (exemple)_哔哩哔哩_bilibili

1. Gestion des pouvoirs

La gestion des droits permet à différents utilisateurs d'accéder uniquement aux ressources dans le cadre de leurs propres droits. Il existe les types suivants

  • Autorité de routage, une fois que l'utilisateur s'est connecté, il ne peut voir le menu de navigation que sous sa propre autorité et ne peut accéder à l'adresse de routage que sous sa propre autorité
  • Afficher les autorisations, les utilisateurs ne peuvent voir que le contenu et les boutons dans leurs autorisations
  • Demande d'autorisation, demande d'ultra-autorité pour l'intercepter

2. Autorité de contrôle

  • Autorisations d'interface
  • autorisations des boutons
  • autorisations de menu
  • autorité de routage

Autorisations d'interface

Une fois que l'utilisateur s'est connecté avec succès, il peut en obtenir un token, tokenl'enregistrer et axiosl'intercepter via l'intercepteur de requête. L'en-tête de la requête doit portertoken

axios.interceptors.request.use(config => {
    config.headers['token'] = cookie.get('token')
    return config
})
axios.interceptors.response.use(res=>{},{response}=>{
    if (response.data.code === 203) { // 登录过期
        router.push('/login')
    }
})

Contrôle de l'autorité de routage

première méthode

Montez toutes les routes lorsque la route est initialisée, marquez les informations d'autorisation correspondantes sur la route et effectuez une vérification lorsque la route saute

const router = [
  {
      path: 'home',
      component: () => import('@/views/home'),
      name: 'homePage',
      meta: {
        title: '主页',
        roles: ['admin','editor'] 
      }
}]

défaut:

  • Toutes les routes seront chargées, et lorsqu'il y a beaucoup de routes, cela aura un impact sur les performances ;
  • Un jugement d'autorisation est requis pour chaque saut de routage ;
  • Les informations du menu sont écrites sur le front-end, et lorsque le titre doit être modifié, il doit être recompilé ;
  • Le menu est couplé à l'itinéraire, et l'itinéraire n'est pas nécessairement affiché sous forme de menu, mais des champs supplémentaires sont nécessaires pour l'identification

Deuxième méthode

Lors de l'initialisation, montez d'abord les routes qui ne nécessitent pas de contrôle d'autorisation, telles que la page de connexion. Si l'utilisateur visite via l'URL, il sera redirigé vers la page 404

addRoutesUne fois connecté, obtenez les informations d'autorisation de l'utilisateur, puis filtrez les routes autorisées à accéder et appelez pour ajouter des routes dans la garde de route globale

function hasPermission(roles, permissionRoles) {
  if (roles.indexOf('admin') >= 0) return true
  if (!permissionRoles) return true
  return roles.some(role => permissionRoles.indexOf(role) >= 0)
}
 
const whiteList = ['/login', '/getMenuLis']
router.beforeEach((to, from, next) => {
    if (getToken()) {
       if (to.path === '/login') {
          next({ path: '/' })
       } else {
          if (store.getters.roles.length === 0) {
            store.dispatch('GetUserInfo').then(res => {
            const roles = res.data.roles 
            store.dispatch('GetRoutes', { roles }).then(() => { 
                router.addRoutes(store.getters.addRouters)
                next({ ...to, replace: true })
          })
      }).catch((err) => {
          store.dispatch('logOut').then(() => {
            Message.error(err)
            next({ path: '/' })
          })
        })
      } else {
        if (hasPermission(store.getters.roles, to.meta.roles)) {
          next()
        } else {
          next({ path: '/401', replace: true, query: { noGoBack: true }})
       }
      }
    }
  } else {
    if (whiteList.indexOf(to.path) !== -1) {
      next()
    } else {
      next('/login')
    }
  }
})

défaut:

  • Dans le garde de routage global, chaque saut de routage doit être jugé
  • Les informations du menu sont en façade, si vous voulez modifier un titre, il faut recompiler
  • Le menu est couplé à l'itinéraire, et l'itinéraire n'est pas nécessairement affiché sous forme de menu, mais des champs supplémentaires sont nécessaires pour l'identification

autorisations de menu

Les autorisations de menu peuvent être comprises comme découplant les pages du routage

première méthode

Le menu est séparé du routage, et le menu est renvoyé par le backend

  1. Le frontal définit les informations de routage
{
    name: "login",
    path: "/login",
    component: () => import("@/pages/Login.vue")
}

namechamp comme identifiant unique du menu retourné par le backend

     2. Porter des jugements dans le Global Routing Guard

function hasPermission(router, accessMenu) {
  if (whiteList.indexOf(router.path) !== -1) {
    return true;
  }
  let menu = Util.getMenuByName(router.name, accessMenu);
  if (menu.name) {
    return true;
  }
    return false;
}
 
Router.beforeEach(async (to, from, next) => {
  if (getToken()) {
    let userInfo = store.state.user.userInfo;
    if (!userInfo.name) {
      try {
        await store.dispatch("GetUserInfo")
        await store.dispatch('updateAccessMenu')
        if (to.path === '/login') {
          next({ name: 'home_index' })
        } else {
          next({ ...to, replace: true })
        }
      }  
      catch (e) {
        if (whiteList.indexOf(to.path) !== -1) {
         next()
        } else {
          next('/login')
        }
      }
    } else {
      if (to.path === '/login') {
        next({ name: 'home_index' })
      } else {
        if (hasPermission(to, store.getters.accessMenu)) {
          Util.toDefaultPage(store.getters.accessMenu,to, routes, next);
       } else {
          next({ path: '/403',replace:true })
        }
      }
    }
  } else {
    if (whiteList.indexOf(to.path) !== -1) {
      next()
    } else {
      next('/login')
    }
  }
  let menu = Util.getMenuByName(to.name, store.getters.accessMenu);
  Util.title(menu.title);
});
 
Router.afterEach((to) => {
  window.scrollTo(0, 0);
});

Chaque fois que l'itinéraire saute, l'autorité doit être jugée. Le jugement ici est également très simple, car le nom du menu correspond au nom de l'itinéraire, et le menu renvoyé par le backend est filtré par l'autorité

Si le menu correspondant ne peut pas être trouvé selon le nom de l'itinéraire, cela signifie que l'utilisateur n'a pas la permission d'accéder

S'il existe de nombreuses routes, vous ne pouvez monter que les routes qui ne nécessitent pas de contrôle d'autorisation lors de l'initialisation de l'application. Après avoir obtenu le menu renvoyé par le backend, filtrez les routes accessibles en fonction de la relation correspondante entre le menu et la route, et montez-les dynamiquement via addRoutes

défaut:

Le menu doit correspondre à l'itinéraire un par un. De nouvelles fonctions ont été ajoutées à l'avant et de nouveaux menus doivent être ajoutés via la fonction de gestion des menus. Si la configuration du menu est incorrecte, l'application ne fonctionnera pas normalement. Dans la garde de route globale, un jugement doit être fait à chaque fois que la route
saute

Deuxième méthode

Le menu et le routage sont renvoyés par le backend

  1. Le frontal définit uniformément les composants de routage
const Home = () => import("../pages/Home.vue");
const UserInfo = () => import("../pages/UserInfo.vue");
export default {
    home: Home,
    userInfo: UserInfo
};

     2. Route de retour en arrière-plan

[
    {
        name: "home",
        path: "/",
        component: "home"
   },
    {
        name: "home",
        path: "/userinfo",
        component: "userInfo"
    }
]

La route renvoyée par le backend est addRoutesmontée dynamiquement, les données doivent être traitées et componentle champ est remplacé par le composant correspondant. Faites attention à la traversée des données de la route imbriquée

défaut:

  • Dans le garde de routage global, chaque saut de routage doit être jugé
  • Nécessite une parfaite coordination des extrémités avant et arrière

autorisations des boutons

première méthode

Faites preuve v-ifde discernement, lorsqu'il y a de nombreuses pages, chaque page doit obtenir des autorisations utilisateur roleet une table de routage meta.btnUse, puis porter des jugements, ce qui est fastidieux

Deuxième méthode

Jugement des autorisations de bouton via des instructions personnalisées

  1. Configurez d'abord le routage
{
    path: 'venueSetting',
    component: _import('venue/venueSetting'),
    name: '场馆设置',
    meta: {
        btnUse: ['admin', 'editor']
    }
},
{
    path: 'fieldSetting',
    component: _import('venue/fieldSetting'),
    name: '场地设置',
    meta: {
        btnUse: ['admin']
    }
}

    2. Authentification d'autorisation personnalisée指令

const has = Vue.directive('has', {
    bind: function (el, binding, vnode) {
        let btnPermissionsArr = [];
        if(binding.value){
            btnPermissionsArr = Array.of(binding.value);
        }else{
            btnPermissionsArr = vnode.context.$route.meta.btnPermissions;
        }
       if (!Vue.prototype.$_has(btnPermissionsArr)) {
          el.parentNode.removeChild(el);
       }
   }
});
// 权限检查方法
Vue.prototype.$_has = function (value) {
    let isExist = false;
    // 获取用户按钮权限
    let btnUseStr = sessionStorage.getItem("btnUse");
    if (btnUseStr == undefined || btnUseStr == null) {
        return false;
    }
    if (value.indexOf(btnUseStr) > -1) {
        isExist = true;
   }
   return isExist;
};
export {has}

v-hasRéférencez la directive dans le bouton utilisé

<el-button @click='editClick' type="primary" v-has>编辑</el-button>

Je suppose que tu aimes

Origine blog.csdn.net/qq_59747594/article/details/130303158
conseillé
Classement