vue要做权限管理该怎么做

  • 权限管理
    • 权限管理概念和方法
    • 权限管理是什么
  • 前端如何做权限控制
    • 接口权限
    • 路由权限
      • 方案一
      • 方案二
    • 菜单权限
      • 方案一
      • 方案二
    • 按钮权限
      • 方案一
      • 方案二
    • 小结

权限管理

权限管理概念和方法

权限管理是指对系统、应用程序或数据资源的访问和使用进行控制和管理的过程。

它确保只有经过授权的用户能够获得适当的权限来执行特定的操作或访问敏感的信息。

权限管理在信息系统安全和数据保护方面起着重要的作用。

在权限管理中,以下是一些常见的概念和方法:

  1. 身份验证(Authentication):身份验证是确认用户身份的过程。通过用户名和密码、指纹、智能卡或其他认证方式,系统可以验证用户是否是其所声称的身份。

  2. 授权(Authorization):授权是系统根据用户的身份和角色,确定用户能够执行的操作和访问的资源。授权通常基于预定义的权限策略和规则来进行。

  3. 角色管理(Role Management):角色是一组具有相似权限需求的用户的集合。通过将用户分配给角色,可以简化权限管理,并确保用户只获得其所需的最低权限。

  4. 权限继承(Permission Inheritance):权限继承是一种层级结构的权限管理方法,其中较高级别的实体(如组织单位)拥有更高级别的权限,而较低级别的实体(如个人用户)继承这些权限。

  5. 最小权限原则(Principle of Least Privilege):最小权限原则指的是给予用户执行任务所需的最低权限,以减少潜在的安全风险。这意味着用户只能访问和操作他们工作所需的资源,而不会被授予超过必要的权限。

  6. 审计与监控(Auditing and Monitoring):审计功能可以跟踪和记录用户对系统和资源的访问日志。监控功能可实时监控用户的行为,并及时检测异常活动或未经授权的访问。

  7. 定期审查(Regular Review):定期审查权限设置和用户权限是一项重要的管理措施,以确保权限与用户的实际需求保持一致,并防止权限的滥用和泄露。

权限管理是确保系统和数据资源安全和保护的关键措施,通过身份验证、授权、角色管理等方法来管理用户的权限,以及通过审计和监控来追踪和防止未经授权的访问。

更多详细内容,请微信搜索“前端爱好者戳我 查看

权限管理是什么

权限是对特定资源的访问许可,所谓权限控制,也就是确保用户只能访问到被分配的资源

而前端权限归根结底是 请求的发起权,请求的发起可能有下面两种形式触发

  • 页面加载触发
  • 页面上的按钮点击触发

所有的请求发起都触发自前端路由或视图

所以我们可以从这两方面入手,对触发权限的源头进行控制,最终要实现的目标是:

  • 路由方面,用户登录后只能看到自己有权访问的导航菜单,也只能访问自己有权访问的路由地址.否则将跳转 4xx 提示页
  • 视图方面,用户只能看到自己有权浏览的内容和有权操作的控件
  • 最后再加上 请求控制 作为最后一道防线,路由可能配置失误,按钮可能忘了加权限,这种时候请求控制可以用来兜底,越权请求将在前端被拦截

前端如何做权限控制

前端权限控制可以分为四个方面

  • 接口权限
  • 按钮权限
  • 菜单权限
  • 路由权限

接口权限

接口权限目前一般采用 jwt 的形式来验证,没有通过的话一般返回 401 ,跳转到登录页面重新进行登录

登录完拿到 token ,将 token 存起来,通过 axios 请求拦截器进行拦截,每次请求的时候头部携带 token

axios.interceptors.request.use(config => {config.headers['token'] = cookie.get('token')return config
})axios.interceptors.response.use(res=>{},{response}=>{if (response.data.code === 40099 || response.data.code === 40098) { //token过期或者错误router.push('/login')}
})

路由权限

方案一

初始化即挂载全部路由,并且在路由上标记相应的权限信息,每次路由跳转前做校验

const routerMap = [{path: '/permission',component: Layout,redirect: '/permission/index',alwaysShow: true, // will always show the root menumeta: {title: 'permission',icon: 'lock',roles: ['admin', 'editor'] // you can set roles in root nav},children: [{path: 'page',component: () => import('@/views/permission/page'),name: 'pagePermission',meta: {title: 'pagePermission',roles: ['admin'] // or you can only set roles in sub nav}}, {path: 'directive',component: () => import('@/views/permission/directive'),name: 'directivePermission',meta: {title: 'directivePermission'// if do not set roles, means: this page does not require permission}}]}
]

这种方式存在以下四种缺点:

  • 加载所有的路由,如果路由很多,而用户并不是所有的路由都有权限访问,对性能会有影响。
  • 全局路由守卫里,每次路由跳转都要做权限判断。
  • 菜单信息写死在前端,要改个显示文字或权限信息,需要重新编译
  • 菜单跟路由耦合在一起,定义路由的时候还有添加菜单显示标题,图标之类的信息,而且路由不一定作为菜单显示,还要多加字段进行标识
方案二

初始化的时候先挂载不需要权限控制的路由,比如登录页,404等错误页。

如果用户通过URL进行强制访问,则会直接进入404,相当于从源头上做了控制

登录后,获取用户的权限信息,然后筛选有权限访问的路由,在全局路由守卫里进行调用 addRoutes 添加路由

import router from './router'
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css'// progress bar style
import { getToken } from '@/utils/auth' // getToken from cookieNProgress.configure({ showSpinner: false })// NProgress Configuration// permission judge function
function hasPermission(roles, permissionRoles) {if (roles.indexOf('admin') >= 0) return true // admin permission passed directlyif (!permissionRoles) return truereturn roles.some(role => permissionRoles.indexOf(role) >= 0)
}const whiteList = ['/login', '/authredirect']// no redirect whitelistrouter.beforeEach((to, from, next) => {NProgress.start() // start progress barif (getToken()) { // determine if there has token/* has token*/if (to.path === '/login') {next({ path: '/' })NProgress.done() // if current page is dashboard will not trigger af terEach hook, so manually handle it} else {if (store.getters.roles.length === 0) { // 判断当前用户是否已拉取完user_info信息store.dispatch('GetUserInfo').then(res => { // 拉取user_info信息const roles = res.data.roles // note:  roles must be a array! such as: ['editor','develop'] store.dispatch('GenerateRoutes', { roles }).then(() => { //根据 roles权限生成可访问的路由表 router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表 next({ ...to, replace: true }) // hack方法 确保addRoutes已完成,set the replace: true so the navigation will not leave a history record })}).catch((err) => {store.dispatch('FedLogOut').then(() => {Message.error(err || 'Verification failed, please login again')next({ path: '/' })})})} else {// 没有动态改变权限的需求可直接next() 删除下方权限判断 ↓if (hasPermission(store.getters.roles, to.meta.roles)) {next()//} else {next({ path: '/401', replace: true, query: { noGoBack: true }})}// 可删 ↑}}
} else {/* has no token*/if (whiteList.indexOf(to.path) !== -1) { // 在免登录白名单,直接进入next()} else {next('/login') // 否则全部重定向到登录页NProgress.done() // if current page is login will not trigger afterE ach hook, so manually handle it}
}
})router.afterEach(() => {NProgress.done() // finish progress bar
})

按需挂载,路由就需要知道用户的路由权限,也就是在用户登录进来的时候就要知道当前用户拥有哪些路由权限

这种方式也存在了以下的缺点:

  • 全局路由守卫里,每次路由跳转都要做判断
  • 菜单信息写死在前端,要改个显示文字或权限信息,需要重新编译
  • 菜单跟路由耦合在一起,定义路由的时候还有添加菜单显示标题,图标之类的信息,而且路由不一定作为菜单显示,还要多加字段进行标识

菜单权限

菜单权限可以理解成将页面与理由进行解耦

方案一

菜单与路由分离,菜单由后端返回, 前端定义路由信息

{name: "login",path: "/login",component: () => import("@/pages/Login.vue")
}

name 字段都不为空,需要根据此字段与后端返回菜单做关联,后端返回的菜单信息中必须要有 name 对应的字段,并且做唯一性校验

全局路由守卫里做判断

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 {//Util.toDefaultPage([...routers], to.name, router, next);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);
});
方案二

菜单和路由都由后端返回

前端统一定义路由组件

const Home = () => import("../pages/Home.vue");
const UserInfo = () => import("../pages/UserInfo.vue");export default {home: Home,userInfo: UserInfo
};

后端路由组件返回以下格式

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

在将后端返回路由通过 addRoutes 动态挂载之间,需要将数据处理一下,将 cmponent 字段换为真正的组件

如果有嵌套路由,后端功能设计的时候,要注意添加相应的字段,前端拿到数据也要做相应的处理

这种方法也会存在缺点:

  • 全局路由守卫里,每次路由跳转都要做判断
  • 前后端的配合要求更高

按钮权限

方案一

按钮权限也可以用 v-if 判断

但是如果页面过多,每个页面页面都要获取用户权限 role 和路由表里的 meta.btnPermissions ,然后再做判断

具体情况如下:

在Vue中,你可以使用路由表中的meta.btnPermissions来进行按钮权限控制。meta.btnPermissions是一个对象,其中包含用于确定按钮是否可见或可用的权限信息。

下面是一个示例,展示了如何使用路由表中的meta.btnPermissions来控制按钮的权限:

  1. 首先,确保你已经安装并配置了Vue Router。
  2. 在你的路由表中,为每个路由添加meta.btnPermissions字段。例如:
const routes = [{path: '/dashboard',component: Dashboard,meta: {btnPermissions: {view: true,edit: false,delete: false,},},},{path: '/users',component: Users,meta: {btnPermissions: {view: true,edit: true,delete: true,},},},// 其他路由...
];

在上述示例中,每个路由都有一个meta.btnPermissions字段,其中包含了该路由相关的按钮权限信息。

你可以根据实际需求设置每个按钮的权限。

  1. 在你的组件中,使用this.$router来访问路由表,并根据当前路由的meta.btnPermissions来控制按钮的显示和可用性。例如:
<template><div><button v-if="checkButtonPermissions('view')">查看</button><button v-if="checkButtonPermissions('edit')">编辑</button><button v-if="checkButtonPermissions('delete')">删除</button></div>
</template><script>
export default {methods: {checkButtonPermissions(permission) {const route = this.$router.currentRoute; // 获取当前路由对象const meta = route.meta.btnPermissions; // 获取当前路由的meta.btnPermissions对象return meta[permission]; // 返回指定权限的值},},
};
</script>

我们通过this.$router.currentRoute获取当前路由对象,然后从路由对象的meta.btnPermissions字段中获取按钮权限信息。

最后,通过checkButtonPermissions方法判断按钮是否可见或可用。你可以根据实际需求调整该方法的实现。

方案二

通过自定义指令进行按钮权限的判断

首先配置路由

{path: '/permission',component: Layout,name: '权限测试',meta: {btnPermissions: ['admin', 'supper', 'normal'] // 页面需要的权限}, children: [{path: 'supper',component: _import('system/supper'),name: '权限测试',meta: {btnPermissions: ['admin', 'supper']} // 页面需要的权限},{path: 'normal',component: _import('system/normal'),name: '权限测试',meta: {btnPermissions: ['admin']} // 页面需要的权限}]
}

自定义权限鉴定指令

import Vue from 'vue'/**权限指令**/
const has = Vue.directive('has', {bind: function (el, binding, vnode) {// 获取页面按钮权限let btnPermissionsArr = [];if(binding.value){// 如果指令传值,获取指令参数,根据指令参数和当前登录人按钮权限做比较。btnPermissionsArr = Array.of(binding.value);}else{// 否则获取路由中的参数,根据路由的btnPermissionsArr和当前登录人按钮权限做比较。btnPermissionsArr = vnode.context.$route.meta.btnPermissions;}if (!Vue.prototype.$_has(btnPermissionsArr)) {el.parentNode.removeChild(el);}}
});// 权限检查方法
Vue.prototype.$_has = function (value) {let isExist = false;// 获取用户按钮权限let btnPermissionsStr = sessionStorage.getItem("btnPermissions");if (btnPermissionsStr == undefined || btnPermissionsStr == null) {return false;}if (value.indexOf(btnPermissionsStr) > -1) {isExist = true;}return isExist;
};export {has}

在使用的按钮中只需要引用 v-has 指令

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

小结

关于权限如何选择哪种合适的方案,可以根据自己项目的方案项目,如考虑路由与菜单是否分离

权限需要前后端结合,前端尽可能的去控制,更多的需要后台判断

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/676724.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

面向工业 X.0 的工业网络简述

此图片来源于网络 1、背景 工业4.0是在21世纪初提出的&#xff0c;特别是在2013年&#xff0c;德国政府正式推出了“工业4.0”战略&#xff0c;旨在通过利用物联网&#xff08;IoT&#xff09;等先进技术提高工业的竞争力。因此&#xff0c;我们可以认为工业4.0的实现时间大致…

安卓服务的常见问题,性能优化以及应用场景剖析

一、引言 在安卓开发中&#xff0c;服务&#xff08;Service&#xff09;扮演着至关重要的角色&#xff0c;它们在没有用户界面的情况下&#xff0c;为用户提供了长时间的后台任务执行能力。本文将探讨服务常见问题、优化策略、应用场景以及开发过程中应注意的事项。 二、应用场…

自己动手打包element UI官方手册文档教程

经常用element ui朋友开发的比较郁闷&#xff0c;官方文档网基本上都是打不开的&#xff0c; 官方&#xff1a;https://element.eleme.io/ 一直打不开&#xff0c;分析下是里面用的cdn链接ssl证书无效。 就想着自己搭建一个element UI文档 自己搭建的&#xff1a; Element文档网…

blender几何节点中样条线参数中的系数(factor)是个什么概念?

一根样条线&#xff0c;通常由两个及以上的控制点构成。 每个控制点的系数&#xff0c;其实相当于该点处位于整个样条线的比值。 如图&#xff0c;一根样条线有十一个控制点。相当于把它分成了十段&#xff0c;那每一段可以看到x、y都是0&#xff0c;唯独z每次增加0.1&#xff…

AutoSAR(基础入门篇)6.2-Adaptive AUTOSAR简介

目录 一、简介 1、传统E/E架构和未来的E/E架构 2、传统汽车和智能汽车 二、Adaptive AUTOSAR介绍

【物联网】继续深入探索ADC模拟转数字的原理——Flash ADC流水线ADC逐次逼近型SAR ADC

这篇文章主要弥补上一篇关于ADC的不足&#xff0c;更加深入了解ADC数模转换器的工作原理&#xff0c;举例常见的三种ADC&#xff0c;分别为Flash ADC&流水线ADC&逐次逼近型SAR ADC。 【物联网】深入了解AD/DA转换技术&#xff1a;模数转换和数模转换 前些天发现了一个巨…

“智能检测,精准把控。温湿度检测系统,为您的生活带来全方位的健康保障。”#非标协议项目【上】

“智能检测&#xff0c;精准把控。温湿度检测系统&#xff0c;为您的生活带来全方位的健康保障。”#非标协议项目【上】 前言预备知识1温湿度检测系统需求2.代码整合2.1找到编程实现LCD1602显示一行工程&#xff0c;打开代码文件&#xff0c;将所需的LCD1602驱动代码拷贝到温湿…

GEE数据——美国农业部LANDFIRE (LF)数据集2.3.0版本

地面火灾数据集 LANDFIRE (LF)&#xff0c;即 "地貌火灾和资源管理规划工具"&#xff0c;是美国农业部森林服务局、美国内政部地质调查局和大自然保护协会的野地火灾管理项目之间的共享项目。前言 – 人工智能教程 LANDFIRE (LF) 图层是利用基于大量实地参考数据、…

2.8日学习打卡----初学RabbitMQ(三)

2.8日学习打卡 一.springboot整合RabbitMQ 之前我们使用原生JAVA操作RabbitMQ较为繁琐&#xff0c;接下来我们使用 SpringBoot整合RabbitMQ&#xff0c;简化代码编写 创建SpringBoot项目&#xff0c;引入RabbitMQ起步依赖 <!-- RabbitMQ起步依赖 --> <dependency&g…

二、OpenAI开发者快速入门

启动并运行OpenAI API OpenAI API 为开发者提供一个简单的接口&#xff0c;使其能够在他们的应用中创建一个智能层&#xff0c;由OpenAI最先进的模型提供支持。聊天补全端点为ChatGPT提示支持&#xff0c;一种简单的方法是&#xff1a;输入文本&#xff0c;使用GPT-4模型输出。…

数据分析报告:直播带货分析与优化(考虑退货)

1. 背景 在直播带货领域赋能是我们的目标&#xff0c;为了实现这一目标&#xff0c;我们需要通过数据分析深入了解直播带货的现状&#xff0c;并制定优化策略。本报告将详细介绍我们的分析思路、具体的分析过程以及最终的结论和优化方向。 2. 思路 为了实现直播带货的赋能&a…

Swift Combine 使用 sink, assign 创建一个订阅者 从入门到精通九

Combine 系列 Swift Combine 从入门到精通一Swift Combine 发布者订阅者操作者 从入门到精通二Swift Combine 管道 从入门到精通三Swift Combine 发布者publisher的生命周期 从入门到精通四Swift Combine 操作符operations和Subjects发布者的生命周期 从入门到精通五Swift Com…

Python进阶:函数式编程

目录 一、前言 二、正文 Ⅰ.核心概念: Ⅱ.优势: Ⅲ.应用场景:

已解决org.aopalliance.aop.AspectException异常的正确解决方法,亲测有效!!!

已解决org.aopalliance.aop.AspectException异常的正确解决方法&#xff0c;亲测有效&#xff01;&#xff01;&#xff01; 文章目录 问题分析 报错原因 解决思路 解决方法 总结 问题分析 在Spring框架的AOP&#xff08;Aspect-Oriented Programming&#xff0c;面向切…

项目02《游戏-12-开发》Unity3D

基于 项目02《游戏-11-开发》Unity3D &#xff0c; 任务&#xff1a;实现场景怪物自动巡航 &#xff0c; 首先在场景中创建小球命名为路径点WayPoint0&#xff0c; 取消小球的碰撞器Collider&#xff0c; 再复制两个改名为WayPoint1 和 WayPoint2 &#xff0c; 在…

Android矩阵Matrix动画缩放Bitmap移动手指触点到ImageView中心位置,Kotlin

Android矩阵Matrix动画缩放Bitmap移动手指触点到ImageView中心位置&#xff0c;Kotlin 借鉴 Android双指缩放ScaleGestureDetector检测放大因子大图移动到双指中心点ImageView区域中心&#xff0c;Kotlin&#xff08;2&#xff09;-CSDN博客 在此基础上实现手指在屏幕上点击后&…

Linux服务器设置 SSH 通过密钥登录(免密登录)

我们一般使用 PuTTY 等 SSH 客户端来远程管理 Linux 服务器。但是&#xff0c;一般的密码方式登录&#xff0c;容易有密码被暴力破解的问题。所以&#xff0c;一般我们会将 SSH 的端口设置为默认的 22 以外的端口&#xff0c;或者禁用 root 账户登录。其实&#xff0c;有一个更…

微服务OAuth 2.1扩展额外信息到JWT并解析(Spring Security 6)

文章目录 一、简介二、重写UserDetailsService三、Controller解析JWT获取用户信息四、后记 一、简介 VersionJava17SpringCloud2023.0.0SpringBoot3.2.1Spring Authorization Server1.2.1Spring Security6.2.1mysql8.2.0 Spring Authorization Server 使用JWT时&#xff0c;前…

生成式人工智能攻击的一年:2024

趋势科技最近公布了其关于预期最危险威胁的年度研究数据。生成人工智能的广泛可用性和质量将是网络钓鱼攻击和策略发生巨大变化的主要原因。 趋势科技宣布推出“关键可扩展性”&#xff0c;这是著名年度研究的新版本&#xff0c;该研究分析了安全形势并提出了全年将肆虐的网络…

用EXCEL从地址(上海)中提取各区(浦东新区等区)信息

背景&#xff1a; 朋友工作需要经常用EXCEL把各上海用户收货地址中的区提取出来&#xff0c;之前一直手动处理&#xff0c;希望我帮忙用EXCEL公式直接提取处理。 数据样式&#xff1a; 中国上海市浦东新区A小区 上海徐汇区B小区 中国&#xff0c;上海&#xff0c;浦东新区&a…