权限管理实现的两种方式(详解)
登录的接口请求的三个内容:
1. token
2. 用户信息、角色信息
3. 菜单信息
第一种:基于角色Role的动态路由管理 (不推荐,但市场用的比较多)
首先列出枚举每个角色对应几个路由,然后根据用户登录的角色遍历枚举出来的角色动态注册对应的路由
const roles = {admin:['所有路由'],'经理':['10个路由'],'运营':['5个路由'],'前台':['2个路由']'新增一个角色':[xxx] ===>改代码重新发布版本
}
这种做法一个弊端:每添加一个角色,都要手动添加代码key:value。最后前端又要发布新的版本(有解决方案如下)
这种方法大致流程如下:
登录:登录验证通过之后后台会返回一个token给前端,前端会保存在vuex和本地(防止刷新丢失登录状态),然后拿token去后台请求一个userInfo的接口获取用户信息(用户名,权限信息等等)
权限验证:通过token获取用户role信息,然后根据用户role算出对应应有权限信息的路由,最后用router.addRotes动态挂载计算出的路由。
代码的实现:
根据token拿到用户信息(权限信息)
这里代码过于简单就不写了,就是请求后台的数据而已。

请求回来的数据保存在Vuex当中(actions发请求----mutations传数据给state,过程不书写了)
//箭头函数
const getDefaultState = () => {return {//获取tokentoken: getToken(),//存储用户名name: '',//存储用户头像avatar: '',//服务器返回的菜单信息【根据不同的角色:返回的标记信息,数组里面的元素是字符串】routes: [],//角色信息roles: [],//按钮权限的信息buttons: [],}
}
vuex查看数据:保存成功

Router中路由的拆分(现在路由是全部注册好的,写死的,不管什么用户看的都是一样的页面。)
分为三类路由:
常量路由,不管什么角色都可以看得路由
任意路由:路径出错的时候重定向404
异步路由:不同角色需要过滤选出路由(根据后台的返回的角色计算出对呀的路由)

store/user.js中对比路由
首先要在state定一个计算好的路由变量resultAsyncRoutes:[] 和一个最终合并展示路由变量resultAllRputes:[]

在获取用户信息的时候异步路由和服务器返回的路由进行对比。commit要提交对比好的路由,所有写一个对比路由函数。computedAsyncRoutes()函数第一个参数是异步路由,第二个是服务器返回的路由。
在actions外面定义一个对比路由的computedAsyncRoutes函数:
//定义一个函数:两个数组进行对比,对比出当前用户到底显示哪些异步路由
const computedAsyncRoutes = (asyncRoutes, routes) => {//过滤出当前用户【超级管理|普通员工】需要展示的异步路由return asyncRoutes.filter(item => {//数组当中没有这个元素返回索引值-1,如果有这个元素返回的索引值一定不是-1 if (routes.indexOf(item.name) != -1) {//递归:别忘记还有2、3、4、5、6级路由if (item.children && item.children.length) {item.children = computedAsyncRoutes(item.children, routes);}return true;}})
}
commit的时候对比好路由(需要深拷贝一下,不然对比后数据影响原数据)

打印异步路由和服务器返回的路由:

然后在mutations中合并路由(计算出来的异步路由,常量路由,任意路由进行合并)用router.addRotes动态挂载计算出的路由。

根据计算出路由展示菜单
目前为止路由都准备好了,但是侧边栏展示还是常量路由,侧边栏应该遍历vuex合并好的路由resultAllRputes
在Sidebar组件中:

这样侧边栏就这根据权限动态展示了。
按钮权限:
菜单权限:不同的用户(角色),能操作、能观看的菜单是不同的。
按钮的权限:不同的用户(角色),有的用户的是可见按钮、当然有的用户不可见。
实现方式也比较简单:根据后台返回button是否有这个按钮的权限值。

用v-if去判断后台返回buttons是否包含该按钮的权限,没有就不显示。
<template><div><el-button type="primary" v-if="$store.state.user.buttons.indexOf('btn.Add1')!=-1">添加按钮1</el-button><el-button type="primary" v-if="$store.state.user.buttons.indexOf('btn.Add2')!=-1">添加按钮2</el-button></div>
</template>
第二种:基于菜单Menu的动态路由管理(推荐)
我这里是从0搭建的,很多细节需要自己处理,看起来比上面的方法麻烦其实不是这样的,上面是使用vue-admin很多细节作者已经处理好了,我这里需要自己处理,也更好的理解各种细节问题。
userMenus =>动态展示菜单
用户管理 ----商品管理----角色管理等等这些路由模块映射成一个对象然后和后端返回这个角色的菜单信息进行对比,然后用Router.addRotes的API动态注册路由。
大致流程:(Vue3+TS+pinia实现)
这里的后台和上面的返回格式不一样,问题也不大。首页还是拿到token,用token拿用户信息,用户信息中有用户id,那个用户id去后台拿菜单信息。

后台返回的菜单信息:

然后对路由进行划分:

对比一下他们的路由信息:

然后进行路由对比,对比好就动态注册路由,要点击登录前就要计算好路由,也就是说push到首页就要算好路由,所有在login中actions进行对比,但是这个逻辑比较多,为了方便管理对比路由函数写在utils
在utils中:
这里用了两个for循环因为这里明确知道两次目录,要是children两层以上可以用递归

在login中actions使用:
计算好的路由放到routes数组中,然后forEach遍历用router.addRoute动态添加路由(addRoute第一个参数是目标路由,第二个参数就是路由信息,代码上的意思就是将遍历出来的路由信息添加main的children下面)

目前效果可以做到点击菜单路由也可以跟着改变了

但是目前有一个问题就是,我注册权限路由是pinia的actions在点击登录按钮的回调进行注册的,现在当我刷新的时候这些路由就访问不到了,只能访问不用权限的路由,为什么会这样?
因为刷新不会重新加载pinia的actions的登录的回调,只有点击登录才会执行,解决办法就是刷新让这个回调重新执行一遍。具体实现如下:
在actions在定一个函数

函数定义好了,要让他刷新执行一遍,需要在main执行(顺序比较重要批念必须先加载,然后再动态注册权限路由,最后加载router)

第一个页面的匹配方法:
现在做一个小细活,就是登录完立刻重定向到第一个页面(这个需要动态的,不是每个角色第一个页面都是一样的)
在那个utils中的mapMenusToRouters函数增加两句代码

然后再router里面的前置守卫使用

根据path匹配menu
现在点击部门管理刷新会跳转到一点页面,我们要的还是留在部门管理这个路由

在nav-menu组件组件中:

计算出defaultActive

在utils写工具函数

大致流程就是这样了。
文章有帮助到您帮忙点个赞赞~~~
相关文章:

权限管理实现的两种方式(详解)
登录的接口请求的三个内容:1. token2. 用户信息、角色信息3. 菜单信息第一种:基于角色Role的动态路由管理 (不推荐,但市场用的比较多)首先列出枚举每个角色对应几个路由,然后根据用户登录的角色遍历枚举出来的角色动态注册对应的路…...
【C++】智能指针思路解析和模拟实现
此篇文章就从以下几个方面出发,带你了解智能指针的方方面面1.为什么需要智能指针当我们开辟内存并使用的时候,我们的顺序应该是这样:开辟内存-》使用内存-》释放内存问题就出现在第三步,开辟好了,也使用了,…...
SpringCloud(18):Sentinel流控降级入门
Sentinel本地应用流控降级实现分为三步: 创建本地应用搭建本地Sentinel控制台本地应用接入本地Sentinel控制台1 本地应用创建 整体流程分析 创建springboot项目在项目的pom.xml文件中引入sentinel-core的依赖坐标创建TestController,定义使用限流规则运行测试具体流程 1.创…...

C++【多态】
文章目录1、多态的概念2、多态的定义及实现2-1、多态的构成条件2-2、虚函数2-3、虚函数的重写2-4 多态样例2-5、协变2-6、 析构函数与virtual2-7、函数重载、函数隐藏(重定义)与虚函数重写(覆盖)的对比2-8、override 和 final&…...
缓存预热、缓存雪崩、缓存击穿、缓存穿透,你真的了解吗?
缓存穿透、缓存击穿、缓存雪崩有什么区别,该如何解决? 1.缓存预热 1.1 问题描述 请求数量较高,大量的请求过来之后都需要去从缓存中获取数据,但是缓存中又没有,此时从数据库中查找数据然后将数据再存入缓存…...

【Java基础】018 -- 面向对象阶段项目上(拼图小游戏)
目录 拼图小游戏(GUI) 一、主界面分析 1、练习一:创建主界面1 2、练习二:创建主界面2(JFrame) 3、练习三:在游戏界面中添加菜单(JMenuBar) ①、菜单的制作 4、添加图片&a…...

【网络~】
网络一级目录二、socket套接字三、UDP数据报套接字四、TCP流套接字一级目录 1.局域网、广域网 2.IP地址是什么? IP地址是标识主机在网络上的地址 IP地址是如何组成的? 点分十进制,将32位分为四个部分,每个部分一个字节ÿ…...
手写JavaScript中的call、bind、apply方法
手写JavaScript中的call、bind、apply方法 call方法 call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。 function Product(name, price) {this.name name;this.price price; }function Food(name, price) {Product.call(this, name, price);t…...
JAVA练习46-将有序数组转换为二叉搜索树
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 前言 提示:这里可以添加本文要记录的大概内容: 2月10日练习内容 提示:以下是本篇文章正文内容,下面案例可供参考 一、题目-…...

linux(centos7.6)docker
官方文档:https://docs.docker.com/engine/install/centos/1安装之前删除旧版本的docker2安装yum install-y yum-utils3配置yum源 不用官网的外国下载太慢 推荐阿里云yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.r…...
微信小程序滚动穿透问题
文章目录1、catchtouchmove"true"2、page-meta3、wx.setPageStyle做小程序的开发业务中,经常会使用弹窗,当弹窗里的内容过多时,要滚动查看,然后经常会遇到滚动弹窗,弹窗底下页面也跟着滚。解决思路ÿ…...

安全—06day
负载均衡反向代理下的webshell上传负载均衡负载均衡下webshell上传的四大难点难点一:需要在每一台节点的相同位置上传相同内容的webshell难点二:无法预测下一次请求是哪一台机器去执行难点三:当我们需要上传一些工具时,麻烦来了&a…...

PostgreSQL入门
PostgreSQL入门 简介 PostgreSQL是以加州大学伯克利分校计算机系开发的POSTGRES, 版本 4.2为基础的对象关系型数据库管理系统(ORDBMS) 支持大部分SQL标准并且提供了许多现代特性 复杂查询外键触发器可更新视图事务完整性多版本并发控制 …...

自媒体人都在用的免费音效素材网站
视频剪辑、自媒体人必备的剪辑音效素材网站,免费下载,建议收藏! 1、菜鸟图库 音效素材下载_mp3音效大全 - 菜鸟图库 菜鸟图库是一个综合性素材网站,站内涵盖设计、图片、办公、视频、音效等素材。其中音效素材就有上千首…...

Java数据结构中二叉树的深度解析及常见OJ题
本篇文章讲述Java数据结构中关于二叉树相关知识及常见的二叉树OJ题做法讲解(包含非递归遍历二叉树) 目录 一、二叉树 1.1二叉树概念 1.2特殊的二叉树 1.3二叉树性质 1.4二叉树基本性质定理题 1.5二叉树遍历基本操作 1.6二叉树遍历的前中后非递归写法 1.7…...

算法顶级比赛汇总
可参赛的算法比赛 阿里云天池大数据竞赛 时间:每年各个季度很多类型都会出题(比赛总时间大概为两个月) 内容:各个类型的算法题都会出、奖金上万不等 形式:在线提交(提交后在线检查结果)、离线…...

Android MVI框架搭建与使用
MVI框架搭建与使用前言正文一、创建项目① 配置AndroidManifest.xml② 配置app的build.gradle二、网络请求① 生成数据类② 接口类③ 网络请求工具类三、意图与状态① 创建意图② 创建状态四、ViewModel① 创建存储库② 创建ViewModel③ 创建ViewModel工厂五、UI① 列表适配器②…...

第九节 使用设备树实现RGB 灯驱动
通过上一小节的学习,我们已经能够编写简单的设备树节点,并且使用常用的of 函数从设备树中获取我们想要的节点资源。这一小节我们带领大家使用设备树编写一个简单的RGB 灯驱动程序,加深对设备树的理解。 实验说明 本节实验使用到STM32MP1 开…...

Ubuntu 系统下Docker安装与使用
Ubuntu 系统下Docker安装与使用Docker安装与使用Docker安装安装环境准备工作系统要求卸载旧版本Ubuntu 14.04 可选内核模块Ubuntu 16.04 使用 APT 安装安装 Docker CE使用脚本自动安装启动 Docker CE建立 docker 用户组测试 Docker 是否安装正确镜像加速Docker使用拉取镜像创建…...

DHCP安全及防范
DHCP安全及防范DHCP面临的威胁DHCP饿死攻击仿冒DHCP Server攻击DHCP中间人攻击DHCP Snooping技术的出现DHCP Snooping防饿死攻击DHCP Snooping防止仿冒DHCP Server攻击DHCP Snooping防止中间人攻击DHCP Snooping防止仿冒DHCP报文攻击DHCP面临的威胁 网络攻击无处不在ÿ…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...

linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...

3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...

华为OD机考-机房布局
import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...

02.运算符
目录 什么是运算符 算术运算符 1.基本四则运算符 2.增量运算符 3.自增/自减运算符 关系运算符 逻辑运算符 &&:逻辑与 ||:逻辑或 !:逻辑非 短路求值 位运算符 按位与&: 按位或 | 按位取反~ …...

海云安高敏捷信创白盒SCAP入选《中国网络安全细分领域产品名录》
近日,嘶吼安全产业研究院发布《中国网络安全细分领域产品名录》,海云安高敏捷信创白盒(SCAP)成功入选软件供应链安全领域产品名录。 在数字化转型加速的今天,网络安全已成为企业生存与发展的核心基石,为了解…...