Table des matières
Recommander la vidéo de la station B
Contrôle de l'autorité de routage
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
, token
l'enregistrer et axios
l'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
addRoutes
Une 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
- Le frontal définit les informations de routage
{
name: "login",
path: "/login",
component: () => import("@/pages/Login.vue")
}
name
champ 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
- 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 addRoutes
montée dynamiquement, les données doivent être traitées et component
le 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-if
de discernement, lorsqu'il y a de nombreuses pages, chaque page doit obtenir des autorisations utilisateur role
et 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
- 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-has
Référencez la directive dans le bouton utilisé
<el-button @click='editClick' type="primary" v-has>编辑</el-button>