Cette fois, je vais vous montrer comment utiliser les autorisations des utilisateurs dans Vue2.0. Quelles sont les précautions pour utiliser les autorisations des utilisateurs dans Vue2.0. Voici des cas pratiques, jetons un coup d'œil.
Vue-Access-Control est une solution frontale de contrôle des autorisations des utilisateurs basée sur Vue/Vue-Router/axios. Elle permet aux développeurs de contrôler le routage, les vues et les requêtes à trois niveaux : Autorisation de l'utilisateur. un contrôle à n’importe quelle granularité peut être réalisé.
Installation
Exigences de la version
Vue 2.0x
Vue-router 3.x
Obtenir
git : git clone https://github.com/tower1229/Vue-Access-Control.git
npm : npm i vue-access-control
Courir
//开发 npm run dev //构建 npm build
Aperçu
Idée globale
Au début de la session, initialisez d'abord une instance Vue avec uniquement le routage de connexion et dirigez le routage vers la page de connexion dans le hook créé par le composant racine Connexion utilisateur Une fois que l'utilisateur s'est connecté avec succès, le front-end. obtient le jeton utilisateur et définit l'instance axios pour unifier la demande. Ajoutez {"Authorization":token} aux en-têtes pour implémenter l'authentification de l'utilisateur, puis obtenez les données d'autorisation de l'utilisateur actuel, qui incluent principalement les autorisations de routage et les autorisations de ressources. ajoutez dynamiquement des routes, générez des menus, implémentez des instructions d'autorisation et des méthodes globales de vérification des autorisations, et fournissez à axios l'instance ajoute un intercepteur de requêtes et l'initialisation du contrôle des autorisations est terminée. Après avoir chargé dynamiquement l'itinéraire, le composant de routage sera chargé et rendu, puis l'interface frontale sera affichée.
Afin de résoudre le problème de réinitialisation de la route d'actualisation du navigateur, après avoir obtenu le jeton, il doit être enregistré dans sessionStorage. Le hook créé du composant racine est chargé de vérifier si le jeton existe déjà localement. Si tel est le cas, ce n'est pas nécessaire. pour vous connecter et utiliser directement le jeton pour obtenir les autorisations et l'initialiser. Si le jeton est valide et que la route actuelle a accès, et que le composant de routage sera chargé et affiché correctement si la route actuelle n'a pas accès, il sautera ; à 404 selon les paramètres de routage ; si le jeton n'est pas valide, le backend doit renvoyer un code d'état 4xx, et le frontend ajoutera uniformément des erreurs à l'instance axios, lorsqu'il rencontrera le code d'état 4xx, effectuera l'opération de sortie, effacera. les données de sessionStorage et accédez à la page de connexion, permettant à l'utilisateur de se reconnecter.
Principe de Dépendance Minimale
Vue-Access-Control se positionne comme une solution à domaine unique. Il n'a pas d'autres dépendances à l'exception de Vue/Vue-Router/axios. En théorie, il peut être appliqué à n'importe quel projet Vue qui a des exigences de contrôle des autorisations. pack Web Dans le cadre du développement de modèles, la plupart des nouveaux projets peuvent être développés directement sur la base du code extrait. Il est à noter que les Element-UI et CryptoJS supplémentaires introduits dans le projet ne sont utilisés que pour développer l'interface de démonstration. Ils ne sont pas nécessaires et n'ont rien à voir avec le contrôle des autorisations. Vous pouvez les choisir vous-même dans l'application du projet.
src/ |-- api/ //接口文件 | |-- index.js //输出通用axios实例 | |-- account.js //按业务模块组织的接口文件,所有接口都引用./index提供的axios实例 |-- assets/ |-- components/ |-- router/ | |-- fullpath.js //完整路由数据,用于匹配用户的路由权限得到实际路由 | `-- index.js //输出基础路由实例 |-- views/ |-- App.vue ·-- main.js
Convention de format de données
Les données d'autorisation de routage doivent être un tableau d'objets au format suivant. Deux routes avec le même identifiant et le même parent_id ont une relation supérieur-subordonné. Si vous souhaitez utiliser les données de routage dans un format personnalisé, vous devez modifier l'implémentation appropriée du contrôle de routage. .
[ { "id": "1", "name": "菜单1", "parent_id": null, "route": "route1" }, { "id": "2", "name": "菜单1-1", "parent_id": "1", "route": "route2" } ]
Les données d'autorisation de ressource doivent être un tableau d'objets au format suivant. Chaque objet représente une requête RESTful et prend en charge les URL avec des paramètres.
[ { "id": "2c9180895e172348015e1740805d000d", "name": "账号-获取", "url": "/accounts", "method": "GET" }, { "id": "2c9180895e172348015e1740c30f000e", "name": "账号-删除", "url": "/account/**", "method": "DELETE" } ]
Contrôle de routage
Le contrôle d'itinéraire comprend deux parties : l'enregistrement dynamique des itinéraires et la génération dynamique des menus.
Parcours d'inscription dynamique
La route initialement instanciée ne comprend que deux chemins : login et 404. Nous nous attendons à ce que la route complète ressemble à ceci :
[{ path: '/login', name: 'login', component: (resolve) => require(['../views/login.vue'], resolve) }, { path: '/404', name: '404', component: (resolve) => require(['../views/common/404.vue'], resolve) }, { path: '/', name: '首页', component: (resolve) => require(['../views/index.vue'], resolve), children: [{ path: '/route1', name: '栏目1', meta: { icon: 'icon-channel1' }, component: (resolve) => require(['../views/view1.vue'], resolve) }, { path: '/route2', name: '栏目2', meta: { icon: 'ico-channel2' }, component: (resolve) => require(['../views/view2.vue'], resolve), children: [{ path: 'child2-1', name: '子栏目2-1', meta: { }, component: (resolve) => require(['../views/route2-1.vue'], resolve) }] }] }, { path: '*', redirect: '/404' }]
Ensuite, vous devez obtenir la page d'accueil et ses sous-itinéraires. L'idée est de stocker localement à l'avance les données de routage complètes de l'ensemble du projet, puis de filtrer les itinéraires complets en fonction des autorisations des utilisateurs.
L'idée d'implémentation du filtrage est de traiter d'abord les données de routage renvoyées par le backend dans la structure de hachage suivante :
let hashMenus = { "/route1":true, "/route1/route1-1":true, "/route1/route1-2":true, "/route2":true, ... }
Parcourez ensuite la route locale complète et divisez le chemin dans le format de clé dans la structure ci-dessus dans la boucle. Vous pouvez juger si la route correspond via hashMenus[route]. Pour une implémentation spécifique, voir la méthode getRoutes() dans l'application. fichier vue.
Si les données d'autorité de routage renvoyées par le backend sont différentes de l'accord, vous devez implémenter vous-même la logique de filtrage. Tant que vous pouvez obtenir les données de routage réellement disponibles, vous pouvez enfin utiliser la méthode addRoutes() pour les ajouter dynamiquement. l'instance de routage. Faites attention à l'ambiguïté de la page 404. La correspondance doit être placée en dernier.
Menu dynamique
路由数据可以直接用来生成导航菜单,但路由数据是在根组件中得到的,导航菜单存在于index.vue组件中,显然我们需要通过某种方式共享菜单数据,方法有很多,一般来说首先想到的是Vuex,但菜单数据在整个用户会话过程中不会发生改变,这并不是Vuex的最佳使用场景,而且为了尽量减少不必要的依赖,这里用了最简单直接的方法,把菜单数据挂在根组件data.menuData上,在首页里用this.$parent.menuData获取。
另外,导航菜单很可能会有添加栏目图标的需求,这可以通过在路由中添加meta数据实现,例如将图标class或unicode存到路由meta里,模板中就可以访问到meta数据,用来生成图标标签。
在多角色系统中可能遇到的一个问题是,不同角色有一个名字相同但功能不同的路由,比如说系统管理员和企业管理员都有”账号管理”这个路由,但他们的操作权限和目标不同,实际上是两个完全不同的界面,而Vue不允许多个路由同名,因此路由的name必须做区分,但把区分后的name显示在前端菜单上会很不美观,为了让不同角色可以享有同一个菜单名称,我们只要将这两个路由的meta.name都设置成”账号管理”,在模板循环时优先使用meta.name就可以了。
菜单的具体实现可以参考views/index.vue。
视图控制
视图控制的目标是根据当前用户权限决定界面元素显示与否,典型场景是对各种操作按钮的显示控制。实现视图控制的本质是实现一个权限验证方法,输入请求权限,输出是否获准。然后配合v-if或jsx或自定义指令就能灵活实现各种视图控制。
全局验证方法
验证方法的的实现本身很简单,无非是根据后端给出的资源权限做判断,重点在于优化方法的输入输出,提升易用性,经过实践总结最终使用的方案是,将权限跟请求同时维护,验证方法接收请求对象数组为参数,返回是否具有权限的布尔值。
请求对象格式:
//获取账户列表 const request = { p: ['get,/accounts'], r: params => { return instance.get(`/accounts`, {params}) } }
权限验证方法$_has()的调用格式:
v-if="$_has([request])"
权限验证方法的具体实现见App.vue中Vue.prototype.$_has方法。
将权限验证方法全局混入,就可以在项目中很容易的配合v-if实现元素显示控制,这种方式的优点在于灵活,除了可以校验权限外,还可以在判断表达式中加入运行时状态做更多样性的判断,而且可以充分利用v-if响应数据变化的特点,实现动态视图控制。
具体实现细节参考基于Vue实现后台系统权限控制中的相关章节。
自定义指令
v-if的响应特性是把双刃剑,因为判断表达式在运行过程中会频繁触发,但实际上在一个用户会话周期内其权限并不会发生变化,因此如果只需要校验权限的话,用v-if会产生大量不必要的运算,这种情况只需在视图载入时校验一次即可,可以通过自定义指令实现:
//权限指令 Vue.directive('has', { bind: function(el, binding) { if (!Vue.prototype.$_has(binding.value)) { el.parentNode.removeChild(el); } } });
自定义指令内部仍然是调用全局验证方法,但优点在于只会在元素初始化时执行一次,多数情况下都应该使用自定义指令实现视图控制。
请求控制
请求控制是利用axios拦截器实现的,目的是将越权请求在前端拦截掉,原理是在请求拦截器中判断本次请求是否符合用户权限,以决定是否拦截。
普通请求的判断很容易,遍历后端返回的的资源权限格式,直接判断request.method和request.url是否吻合就可以了,对于带参数的url需要使用通配符,这里需要根据项目需求前后端协商一致,约定好通配符格式后,拦截器中要先将带参数的url处理成约定格式,再判断权限,方案中已经实现了以下两种通配符格式:
1. 格式:/resources/:id 示例:/resources/1 url: /resources/** 解释:一个名词后跟一个参数,参数通常表示名词的id 2. 格式:/store/:id/member 示例:/store/1/member url:/store/*/member 解释:两个名词之间夹带一个参数,参数通常表示第一个名词的id
对于第一种格式需要注意的是,如果你要发起一个url为"/aaa/bbb"的请求,默认会被处理成"/aaa/**"进行权限校验,如果这里的”bbb”并不是参数而是url的一部分,那么你需要将url改成"/aaa/bbb/",在最后加一个”/“表示该url不需要转化格式。
Pour l'implémentation spécifique de l'intercepteur, voir la méthode setInterceptor() dans App.vue.
Si votre projet nécessite d'autres formats de caractères génériques, il vous suffit d'implémenter les méthodes de détection et de conversion correspondantes dans l'intercepteur.
Démonstration et explication
Description de la démo :
Le projet DEMO démontre le menu dynamique, le routage dynamique, les autorisations des boutons et l'interception des demandes.
Le backend du projet de démonstration génère des données fictives par rap2. La demande de connexion doit généralement être en mode POST. Cependant, comme le mode de programmation de rap2 ne peut pas obtenir les paramètres de requête non GET , la méthode GET peut donc le faire. être utilisé uniquement pour se connecter. Dans le projet actuel Non recommandé à suivre
De plus, l'interface permettant d'obtenir les autorisations après la connexion n'a pas besoin de comporter de paramètres supplémentaires. Le backend peut implémenter l'authentification de l'utilisateur sur la base des informations de jeton contenues dans l'en-tête de la requête. Cependant, le mode de programmation de rap2 ne pouvant pas obtenir les données d'en-tête. ne peut ajouter qu'un paramètre "Autorisation" Utilisé pour générer des données de simulation. Je pense que vous maîtrisez la méthode après avoir lu le cas dans cet article. Pour des informations plus intéressantes, veuillez prêter attention aux autres articles connexes sur le site Web chinois de php ! Lecture recommandée :node.js réalise le fonctionnement d'un terminal Web multi-utilisateurs
Ajouter une boîte de dialogue contextuelle dans WeChat Boîte d'applets
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!