位运算在权限授权中的应用及Vue3实践

在现代前端应用中,权限管理是一个至关重要的功能模块。随着应用复杂度的提示功能,权限细粒度越来越精细,如何高效地管理和判断权限成为前端开发的一大挑战。位运算作为一种高效的运算方式,在权限管理领域有着独特的优势。本文将详细介绍位运算在权限授权中的应用,并结合Vue3框架展示具体实现。

位运算与权限管理的天然契合

权限管理的核心需求可以概括为:表示权限集合、添加权限、移除权限和验证权限。这恰好与位运算的特性高度匹配。

位运算的优势:

  • 高效性:直接操作二进制,性能远优于数组或对象操作
  • 简洁性:用一个整数即可表示多个权限的数组状态
  • 扩展性:轻松添加新权限类型,不影响已有逻辑
  • 内存友好:一个32位整数可表示32种不同权限,64位整数则可表示64种

核心位运算原理

在权限管理中,我们主要使用以下四种位运算:

  1. 按位或(|=)添加权限
userPermissions != permission;
  1. 按位与(&)验证权限
const hasPermission = (userPermission & permission) !== 0;
  1. 按位与非(&=~)移除权限
userPermissions &= ~permission;
  1. 按位异或(^=)切换权限
userPermissions ^= permission;

权限设计模式

权限定义

首先为每种权限定义一个唯一的标识符,采用2的幂次方形式:

// src/enums/permission.ts
export enum Permission {// 基础权限VIEW = 1 << 0, // 1 (二进制:0001)- 查看权限EDIT = 1 << 1, // 2 (二进制:0010)- 编辑权限DELETE = 1 << 2, // 4 (二进制:0100)- 删除权限CREATE = 1 << 3, // 8 (二进制:1000) - 创建权限// 高级权限APPROVE = 1 << 4, // 16 - 审批权限EXPORT = 1 << 5, // 32 - 导出权限IMPORT = 1 << 6, // 64 - 导入权限// 管理员权限ADMIN = VIEW | EDIT | DELETE | CREATE | APPROVE | EXPORT | IMPORT
}// 权限描述信息
export const PermissionDesc = {[Permission.VIEW]: {name: '查看', description: '查看内容的权限'},[Permission.EDIT]: {name: '编辑', description: '编辑内容的权限'},[Permission.DELETE]: {name: '删除', description: '删除内容的权限'},[Permission.CREATE]: {name: '创建', description: '创建内容的权限'},[Permission.APPROVE]: {name: '审批', description: '审批内容的权限'},[Permission.EXPORT]: {name: '导出', description: '导出内容的权限'},[Permission.IMPORT]: {name: '导入', description: '导入内容的权限'},[Permission.ADMIN]: {name: '管理员', description: '拥有所有的权限'}
}

权限管理工具类

封装一个权限管理工具类,提供权限操作的核心方法:

// src/utils/permissionManager.ts
import { Permission } fro '@enums/permissions';class PermissionManager {private permissions: number;constructor(initialPermissions: number = 0){this.permissions = initialPermissions;}/*** 添加权限* @param permission 权限值,可以是单个权限或多个权限的组合*/add(permission: Permission): void {this.permissions != permission;}/*** 移除权限* @param permission 权限值,可以是单个权限或多个权限的组合*/remove(permission: Permission): void {this.permissions &= ~permission;}/*** 检查是否拥有指定权限* @param permission 权限值,可以是单个权限或多个权限的组合* @returns 是否拥有权限*/has(permission: Permission): boolean {return(this.permissions & permission) !== 0;}/*** 切换权限状态* @param permission 权限值*/toggle(permission: Permission): void {this.permission ^= permission;}/*** 获取当前所有权限值* @returns 权限值*/getValue(): number {return this.permissions;}/*** 重置权限* @param permissions 新的权限值,默认为0(无权限)*/reset(permissions: number = 0): void {this.permissions = permissions;}
}export default PermissionManager;

Vue3中的实践应用

全局权限状态管理

使用Pinia存储全局权限状态,便于在整个应用中共享和访问:

// src/stores/permissionStore.ts
import { defineStore } from 'pinia';
import PermissionManager from '@/utils/permissionManager';
import { Permission } from '@/enums/permissions';export const usePermissionStore = defineStore('permission', {state: () => ({manager: new PermissionManager(),initialized: false}),actions: {async init() {try {// 实际项目中从接口中获取// 这里模拟获取权限值const permissionValue = Permission.VIEW | Permission.EDIT | Permission.CREATE;this.manager.reset(permissionValue);this.initialized = true;} catch(error){this.initialized = false;}},addPermission(permission: Permission) {this.manager.add(permission)},removePermission(permission: Permission) {this.manager.remove(permission)},hasPermission(permission: Permission): boolean{return this.manager.has(permission);},togglePermission(permission: Permission) {this.manager.toggle(permission)}}
})

权限指令

创建自定义指令,用于在模版中控制元素的显示或操作权限:

// src/directives/permission.ts
import { DirectiveBinding } from 'vue';
import { usePermissionStore } from '@/stores/permissionStore';
import { Permission } from '@/enums/permissions';export default {mounted(el: HTMLElement, binding: DirectiveBinding){const permissionStore = usePermissionStore();const requiredPermission = binding.value as Permission;// 检查是否有权限const hasPermission = permissionStore.hasPermission(requiredPermission);// 如果没有权限,移除元素或禁用元素if(!hasPermission) {if(binding.modifiers.disabled) {el.disabled = true;el.classList.add('opacity-50', 'cursor-not-allowed');} else {el.parentNode?.removeChild(el);}}}
}

在main.ts中注册指令:

// src/main.ts
import { createApp } from 'vue';
import App from './App.vue';
import permissionDirective from './directives/permission';const app = createApp(App);
app.directive('permission', permissionDirective);
app.mount('#app');

权限组件

创建一个权限检查组件,用于包裹需要控制权限的内容:

<template><slot v-if="hasPermission"></slot><slot name="fallback" v-else></slot>
</template><script setup lang="ts">
import { defineProps, computed } from 'vue';
import { usePermissionStore } from '@/stores/permissionStore';
import { Permission } from '@/enums/permissions';const props = defineProps<{required: Permission
}>();const permissionStore = usePermissionStore();
const hasPermission = computed(()=> {return permissionStore.hasPermission(props.required)
})
</script>

在组件中使用

 <template><div class="permission-demo"><!-- 指令控制按钮是否显示 --><button v-permission:[Permission.EDIT]>编辑</button><!-- 无权限时禁用 --><button v-permission:[Permission.DELETE].disabled>删除</button><!-- 使用权限组件控制区域 --><PermissionGuard :required="Permission.CREATE"><div class="create-content"><!-- 创建区域 --></div><template #fallback><div class="no-permission">没有创建权限</div></template></PermissionGuard><!-- 权限状态展示 --><div class="permission-status"><h3>当前权限状态</h3><ul><li v-for="(desc, perm) in PermissionDesc" :key="perm"><div :class="'has-perm': hasPermission(perm)">{{desc.name}}: {{hasPermission(perm) ? '已拥有' : '未拥有'}}</div></li></ul><!-- 权限操作按钮 --><div class="permission-actions"><button @click="togglePermission(Permission.DELETE)">切换删除权限</button><button @click="togglePermission(Permission.ADMIN)">切换管理员权限</button></div></div></div>
</template>
<script setup lang="ts">
import { Permission, PermissionDesc } from '@/enums/permissions';
import { usePermissionStore } from '@/stores/permissionStore';
import PermissionGuard from '@/components/PermissionGuard.vue';const permissionStore = usePermissionStore();
// 检查权限
const hasPermission = (perm: Permission) => {return permissionStore.hasPermission(perm)
}
// 切换权限
const togglePermission = (perm: Permission) => {permissionStore.togglePermission(perm)
}
</script><style scoped>
.has-perm {color: green;font-weight: bold;
}.no-permission {color: #999;padding: 1rem;border: 1px dashed #ccc;border-radius: 4px;
}.permission-actions {margin-top: 1rem;display: flex;gap: 0.5rem;
}button {margin: 0.5rem;padding: 0.5rem 1rem;cursor: pointer;
}button:disabled {cursor: not-allowed;
}

权限系统的扩展与优化

  1. 权限组管理:对于复杂应用,可以将权限分组管理,每组权限使用独立的位段。
  2. 权限缓存:将用户权限缓存到localStorage或sessionStorage中,减少重复请求。
  3. 权限验证中间件:在路由导航时添加权限验证,防止未授权方位。
// src/router/permissionGuard.ts
import { NavigationGuardNext, RouteLocationNormalized } from 'vue-router';
import { usePermissionStore } from '@/stores/permissionStore';
import { Permission } from '@/enums/permissions';interface RouteMeta {requiredPermission?: Permission;
}export function permissionGuard(to: RouteLocationNormalized & { meta: RouteMeta },from: RouteLocationNormalized,next: NavigationGuardNext
){const permissionStore = usePermissionStore();const requiredPermission = to.meta.requiredPermission;// 如果路由不需要权限,直接放行if(!requiredPermission) {next();return;}// 检查是否有权限if(permissionStore.hasPermission(requiredPermission)) {next();} else {// 无权限,重定向到无权限页面next('/no-permission')}
}

总结

位运算为前端权限管理提供了一种高效、简洁的解决方案。通过合理设计权限体系,并结合Vue3的响应式系统、状态管理和自定义指定,可以构建出灵活且高性能的权限管理模块。

在实际项目中,应根据应用的复杂度和权限需求选择合适的权限设计方案。对于中小型应用,本文介绍的位运算方案足够应对大多数场景;对于超大型应用,可能需要结合更复杂的权限模型,但位运算依然可以作为底层的高效运动方式发挥重要作用。

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

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

相关文章

面试实战,问题二十二,Java JDK 17 有哪些新特性,怎么回答

Java JDK 17 新特性面试回答指南 作为一名Java开发者&#xff0c;了解JDK 17的新特性是面试中的关键点。JDK 17&#xff08;Java SE 17&#xff09;于2021年9月发布&#xff0c;是一个长期支持&#xff08;LTS&#xff09;版本&#xff0c;引入了多项改进以提升开发效率、安全性…

【MySQL安全】什么是SQL注入,怎么避免这种攻击:前端防护、后端orm框架、数据库白名单

基本概念SQL注入是OWASP Top 10安全风险之一&#xff0c;它利用了应用程序对用户输入数据的不当处理。当应用程序直接将用户输入拼接到SQL查询中而没有进行适当的过滤或转义时&#xff0c;就可能发生SQL注入攻击。攻击原理假设有一个登录表单的SQL查询&#xff1a;SELECT * FRO…

pyqt5显示任务栏菜单并隐藏主窗口,环境pyqt5+vscode

环境 pyqt5vscode 环境搭建见 https://blog.csdn.net/huiaifen/article/details/125175261 新建一个QMainWindow 1 在VSCode的资源管理器中&#xff0c;右键选择 PYQT:New Form&#xff0c;打开Qt Designer2 在打开的窗口中选 “Main Window”&#xff0c;然后选“创建”3 直接…

SpringBoot项目数据脱敏(自定义注解)

文章目录前言一.配置1.脱敏类型枚举&#xff1a;DesensitizeType2.注解&#xff1a;Desensitize3.序列化类&#xff1a;DesensitizeJsonSerializer4.工具类&#xff1a;DesensitizeUtil二、测试&#xff1a;DesensitizeTest三、效果展示总结前言 在互联网应用中&#xff0c;用户…

PSO-TCN-BiLSTM-MATT粒子群优化算法优化时间卷积神经网络-双向长短期记忆神经网络融合多头注意力机制多特征分类预测/故障诊断Matlab实现

基本介绍 1.Matlab实现PSO-TCN-BiLSTM-MATT粒子群算法优化时间卷积神经网络-双向长短期记忆神经网络融合多头注意力机制多特征分类预测&#xff0c;PSO-TCN-BiLSTM-Multihead-Attention&#xff1b; 多头自注意力层 (Multihead-Self-Attention)&#xff1a;Multihead-Self-Atte…

第一篇:Linux 运维入门:虚拟机部署与基础环境配置

目录 一、准备工作与环境规划 二、虚拟机网络配置 1、虚拟网络编辑器设置 2、系统网络配置 3、主机名配置 三、Hosts 文件与 SSH 免密配置 配置 hosts 文件编辑/etc/hosts文件实现主机名解析&#xff1a; 分发 hosts 文件到其他节点 SSH 免密登录配置在 zhangsan101 上…

(一)全栈(react配置/https支持/useState多组件传递/表单提交/React Query/axois封装/Router)

文章目录 项目地址 一、基础配置 1.1 支持https 1. 安装所需要的包 2. 配置 1.2 常用 1. 字符串拼接 二、组件 2.1 useState组件传递 1. App里初始化useState 2. useState和方法的传递 3. 接收传递来的状态和方法 2.2 表单提交 1. 表单组件处理用户输入数据 2. App传来的submit…

【abc417】E - A Path in A Dictionary

Problem StatementYou are given a simple connected undirected graph G with N vertices and M edges. The vertices of G are numbered vertex 1, vertex 2, …, vertex N, and the i-th (1≤i≤M) edge connects vertices Ui​ and Vi​.Find the lexicographically smalle…

linux火焰图

火焰图简介火焰图是一种性能分析的可视化工具&#xff0c;它将CPU的调用栈&#xff08;Call Stack&#xff09;信息以矩形火焰的形式展现出来。Y轴&#xff1a;代表调用栈的深度&#xff08;函数A调用了函数B&#xff0c;B就叠在A上面&#xff09;。X轴&#xff1a;代表CPU的抽…

解剖 .NET 经典:从 Component 到 BackgroundWorker

1️⃣ 背景与定位在 .NET Framework 2.0 时代&#xff0c;微软引入了 BackgroundWorker 来解决 WinForm/WPF 场景下“耗时操作阻塞 UI 线程”的问题&#xff1b;而 Component 早在 1.0 就已存在&#xff0c;是所有可视化/非可视化设计器的“基类”。理解这两者的源码与机制&…

桌面端界面设计 |货物 TMS 系统 - SaaS UI UX 设计:审美积累之境

在物流数字化的浪潮中&#xff0c;货物 TMS 系统的 SaaS 化与 UI/UX 设计正构建着独特的审美坐标系。这不仅是技术与功能的融合&#xff0c;更是一场关于效率美学的深度探索&#xff0c;为行业审美积累注入了鲜活的实践样本。SaaS 模式赋予货物 TMS 系统轻盈而强大的特质&#…

多架构镜像整合全攻略:在Docker中实现单一镜像支持同时支持amd64和arm64架构

多架构支持的挑战 &#xff1a;随着异构计算&#xff08;如 ARM、x86、RISC-V 等&#xff09;的普及&#xff0c;开发者需要为不同硬件平台提供对应的镜像&#xff0c;传统方式需维护多个版本&#xff08;如 image:v1-amd64 和 image:v1-arm64 &#xff09;&#xff0c;导致版本…

Linux730 tr:-d /-s;sort:-r,-n,-R,-o,-t,-k,-u;bash;cut:-d,-c;tee -a;uniq -c -i

回顾 sort sort [选项] 文件-u&#xff1a;唯一&#xff0c;去除重复 -r:按数字大小&#xff0c;倒序排序&#xff0c;大到小 -o:输出文件 -n:按数字大小&#xff0c;顺序排序&#xff0c;小到大 -t: -t后加分割符&#xff0c;按分割符为标准&#xff0c;进行筛选 -k:k后加数字…

力扣457:环形数组是否存在循环

力扣457:环形数组是否存在循环题目思路代码题目 存在一个不含 0 的 环形 数组 nums &#xff0c;每个 nums[i] 都表示位于下标 i 的角色应该向前或向后移动的下标个数&#xff1a; 如果 nums[i] 是正数&#xff0c;向前&#xff08;下标递增方向&#xff09;移动 |nums[i]| 步…

在 Elasticsearch 中落地 Learning to Rank(LTR)

1 为什么要引入 LTR&#xff1f; 常规检索&#xff08;BM25、语义检索、Hybrid、RRF …&#xff09;往往只能基于少量信号&#xff08;关键词命中、向量相似度&#xff09;排序。 Learning-to-Rank 通过机器学习模型把多维度特征&#xff08;文档属性、查询属性、查询-文档相关…

Socket编程——TCP协议

文章目录一、TCP传输二、相关接口三、多进程版本四、多线程版本一、TCP传输 TCP和UDP类似&#xff0c;但是在传输中TCP有输入&#xff0c;输出缓冲区&#xff0c;看下面的传输图片 可以理解为TCP之间的数据传输都是依赖各自的socket&#xff0c;socket就充当传输的中介吧。 而…

GitHub使用小记——本地推送、外部拉取和分支重命名

GitHub 项目推送与拉取等操作使用随记 本小记适用于个人项目或组织项目&#xff0c;涵盖 GitHub 推送、拉取、分支管理、.gitignore 设置等常见需求。 1. 将已有本地工程推送至 GitHub 新仓库 1.1 前提条件 本地项目结构完整&#xff0c;已准备好&#xff1b;本地已安装 Git…

RabbitMQ 延时队列插件安装与使用详解(基于 Delayed Message Plugin)

RabbitMQ 延时队列插件安装与使用详解&#xff08;基于 Delayed Message Plugin&#xff09;&#x1f4cc; 一、什么是 RabbitMQ 延时队列&#xff1f;&#x1f680; 二、安装前准备✅ RabbitMQ 环境要求&#x1f527; 三、安装延时队列插件&#x1f9e9; 插件名称&#xff1a;…

Vue项目使用ssh2-sftp-client实现打包自动上传到服务器(完整教程)

告别手动拖拽上传&#xff01;本教程将手把手教你如何通过ssh2-sftp-client实现Vue项目打包后自动上传到服务器&#xff0c;提升部署效率300%。&#x1f680;一、需求场景与解决方案在Vue项目开发中&#xff0c;每次执行npm run build后都需要手动将dist目录上传到服务器&#…

《质光相济:Three.js中3D视觉的底层交互逻辑》

在Three.js搭建的虚拟维度中,光照与材质的关系远非技术参数的简单叠加,当光线以数字形态穿越虚空,与物体表面相遇的瞬间,便开始书写属于这个世界的物理叙事——每一缕光斑的形状、每一块阴影的浓淡、每一寸肌理的反光,都是对现实光学规律的转译与重构。理解这种交互的深层…