vue3中基于路由层面和组件层面进行用户角色及权限控制的方法解析

news2024/11/28 12:41:54

文章目录

      • 一、权限控制
      • 二、路由层面控制
      • 三、组件层面控制
        • 1、使用自定义指令
        • 2、使用方法控制
        • 3、封装一个权限控制组件来实现组件层面控制权限
          • 3.1、组件页面 Authority.vue
          • 3.2、使用页面 app.vue
          • 3.3、效果预览

一、权限控制

随着前端技术的不断发展,越来越多的前端框架被使用在 Web 应用程序中,其中尤为出色的一个就是 Vue。Vue 是一个易于理解并且使用方便的框架,它被广泛地应用于 Web 应用程序的开发中。在大多数 Web 应用程序中,权限控制是至关重要的一部分,如何在 Vue 中进行权限控制就成为了一个十分关键的问题。

权限控制是一个很重要的概念,在 Web 应用程序中尤其重要。简单地说,权限控制就是将用户分为不同的分类,为每个分类分配相应的用户权限。这样,用户就只能访问他们所允许的内容了。权限控制可以提高应用程序的安全性和稳定性,使数据更加安全可靠。

在 Vue 中进行权限控制,通常有两种方式:第一种是在路由层面进行控制,第二种是在组件层面进行控制。

用户登录后该用户的角色与权限信息会一同返回给前端,前端将这些信息存储到状态管理里备用即可。

  • 这里使用pinia存储当前用户的角色及权限。你可以根据实际情况进行相应的调整。

  • store/index.js

import { defineStore } from 'pinia'
import { ref } from 'vue';

export const userPermissionsStore = defineStore('userPermissions', () => {
  // 角色
  const roles = ref('admin')

  // 权限
  const userPermissions = ref([])

  //是否登录
  const isLogin = ref(false)

  // 设置状态(传入的权限信息赋值给该状态)
  const setUserPermissions = (params) => {
    userPermissions.value = params
  }

  return {
    isLogin,
    userPermissions,
    roles,
    setUserPermissions
  }
})

二、路由层面控制

在路由层面进行控制,可以在路由的元数据 meta 中设置用户权限,然后可以在路由守卫函数中进行校验。如果当前用户的权限符合该路由的要求,则策略继续进行,否则将导航到其他页面。

路由的元数据 meta 中设置了 requireAuth 和 roles 两个属性,requireAuth 表示该路由需要用户登录才能访问,roles 表示受访问限制的角色。可以在 beforeEach 路由守卫函数中校验用户权限,如果用户有访问该路由的权限,则进入页面,否则跳转到其他页面。这样,就可以在路由层面进行权限控制了。

import { createRouter, createWebHashHistory } from 'vue-router'
import { userPermissionsStore } from '@/store/index'
import { storeToRefs } from 'pinia'

let routes = [{
  path: '/home', // 路径
  name: 'home', // 路由名称
  component: () => import('../views/home.vue'),
  meta: {
    requireAuth: true, // 需要用户权限
    roles: ['admin', 'guest'] // 受访问限制的角色
  }
}, {
  path: '/login', 
  name: 'login', 
  component: () => import('../views/login.vue')
}, {
  path: '/denied', 
  name: 'denied', 
  component: () => import('../views/denied.vue')
}]

const router = createRouter({
  history: createWebHashHistory(),
  routes
})

// 添加路由前置守卫
router.beforeEach((to, from, next) => {
  const store = userPermissionsStore()
  // 获取当前登录状态及用户角色
  const { isLogin, roles } = storeToRefs(store)
  // 判断该路由是否需要登录权限
  if (to.meta.requireAuth) {
    // 如果需要,则校验用户是否已经登录
    if (isLogin.value) {
      // 判断当前用户是否有访问该路由的权限
      if (to.meta.roles.includes(roles.value)) {
        next() // 用户有访问权限,直接进入页面
      } else {
        next('/denied') // 跳转到其他页面
      }
    } else {
      // 如果用户未登录,则跳转到登录页面
      next('/login')
    }
  } else {
    next() // 如果不需要登录权限,直接进入页面
  }
});

export default router

三、组件层面控制

1、使用自定义指令

可以利用 Vue 的指令来控制组件的显示和隐藏。例如,可以为每个组件设置一个权限属性,然后在指令中判断当前用户是否有访问该组件的权限,如果有,则显示组件,否则隐藏组件。利用 v-if 指令来判断当前用户是否有访问该组件的权限,并根据权限设置组件的显示和隐藏。

<template> 
    <el-button type="success" plain v-permission="'sys:user:add'">添加用户1</el-button>
</template> 

<script setup> 
import { userPermissionsStore } from '@/store/index'
import { storeToRefs } from 'pinia'
const store = userPermissionsStore()
const { userPermissions } = storeToRefs(store)

const vPermission = {
  mounted(el, binding) {
    const requiredPermission = binding.value;
    if (!userPermissions.value.includes(requiredPermission)) {
      el.style.display = 'none';
    }
  }
} 
</script>
2、使用方法控制
<template> 
     <el-button type="primary" plain v-if="hasPermission('sys:user:add')">添加用户1</el-button>
</template> 

<script setup> 
import { userPermissionsStore } from '@/store/index'
import { storeToRefs } from 'pinia'
const store = userPermissionsStore()
const { userPermissions } = storeToRefs(store)

const hasPermission = (permission) => {
  return userPermissions.value.includes(permission);
}
</script>
3、封装一个权限控制组件来实现组件层面控制权限
3.1、组件页面 Authority.vue
<template>
    <slot v-if="showSlot" :userPermissions="userPermissions"></slot>
</template>

<script setup>
import { computed } from 'vue';

import { storeToRefs } from 'pinia'
import { userPermissionsStore } from '@/store/index'
const store = userPermissionsStore()
// 为了从 store 中提取属性时保持其响应性,你需要使用 storeToRefs()
const { userPermissions } = storeToRefs(store)

const props = defineProps({
	// 需要的权限
    permissions: {
        type: [String, Array]
    }
});

const showSlot = computed(() => {
    if (!props.permissions) {
        return true
    }
    if (!userPermissions.value) {
        return false
    }
    if (Array.isArray(props.permissions)) {
        return props.permissions.every(p => {
            return userPermissions.value.includes(p)
        })
    } else {
        return userPermissions.value.includes(props.permissions)
    }
})

</script>

<style scoped>
</style>
3.2、使用页面 app.vue
<template>
  <el-select v-model="value" placeholder="请选择" @change="change" style="width: 300px; margin: 20px 0;">
    <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
  </el-select>

  <div>
    <!-- 这里可以根据返回的权限,做自己想判断的事情 -->
    <Authority>
      <template #default="{ userPermissions }">
        <el-button :disabled="!userPermissions.includes('sys:user:delete')" type="primary">禁用用户1</el-button>
      </template>
    </Authority>
    <!-- 传入组件所需要的权限 -->
    <Authority permissions="sys:user:view">
      <el-button>查询用户2</el-button>
    </Authority>
    <Authority permissions="sys:user:update">
      <el-button type="success">修改用户3</el-button>
    </Authority>
    <Authority permissions="sys:user:delete">
      <el-button type="info">删除用户4</el-button>
    </Authority>
    <Authority permissions="sys:user:add">
      <el-button type="warning">添加用户5</el-button>
    </Authority>
    <Authority :permissions="['sys:user:update', 'sys:user:delete']">
      <el-button type="danger">禁用用户6</el-button>
    </Authority>
  </div>
</template>

<script setup>
import Authority from '@/components/Authority.vue'
import { ref } from 'vue'

const value = ref('')
const options = [{
  value: '0',
  label: 'admin',
  permissions: ["sys:user:view", "sys:user:update", "sys:user:delete", "sys:user:add"]
}, {
  value: '1',
  label: 'editor',
  permissions: ["sys:user:view", "sys:user:update", "sys:user:add"]
}, {
  value: '2',
  label: 'guest',
  permissions: ["sys:user:view"]
}]

import { userPermissionsStore } from '@/store/index'
const store = userPermissionsStore()
// 作为 action 的 setUserPermissions 可以直接解构
const { setUserPermissions } = store
const change = (e) => {
  setUserPermissions(options[e].permissions)
}

</script>

<style scoped>
</style>
3.3、效果预览

这里使用el-select下拉框切换用户角色,存储pinia,是为了演示不同用户,不同的角色权限切换效果。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

美食推荐|美食推荐小程序|基于微信小程序的美食推荐系统设计与实现(源码+数据库+文档)

美食推荐小程序目录 目录 基于微信小程序的美食推荐系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、前台功能模块 2、后台功能模块 &#xff08;1&#xff09;用户信息管理 &#xff08;2&#xff09;水果信息管理 &#xff08;3&#xff09;水果类型管理…

投票助力 | 第19届(2023)数智招标采购行业年度评选网络投票已开启!

为展示招标采购领域业务发展的突出成绩和数智化应用创新成果&#xff0c;以优秀企业、个人和案例激励并引导更多的行业实践者们共同努力&#xff0c;推进招标采购行业数智化创新发展&#xff0c;必联网、机电产品招标投标电子交易平台、隆道平台、隆道研究院联合主办了“第19届…

讲技巧乘机会

恋爱季节 - 邓丽君 (Teresa Teng) 词&#xff1a;邓丽君 曲&#xff1a;いずみたく 太阳高天气真晴朗 微风里飘来野花香 手拉手并肩向前走 我和你来到小溪旁 爬过了山坡又村庄 经过了小桥和池塘 我和你歌唱在山岗 青山绿水回声响 谈恋爱要有勇气 要赶快 讲技巧乘机…

HTML 入门指南

简述 参考&#xff1a;HTML 教程- (HTML5 标准) HTML 语言的介绍、特点 HTML&#xff1a;超级文本标记语言&#xff08;HyperText Markup Language&#xff09; “超文本” 就是指页面内可以包含图片、链接等非文字内容。“标记” 就是使用标签的方法将需要的内容包括起来。…

当excel中表格打印预览右边超出限定页面时,调整列宽

解决办法&#xff1a;调整整体列或者部分列的列宽 操作流程如下&#xff1a; 第一步&#xff1a;选中需要调整的列 ①将鼠标放在表格的列上&#xff0c;等出现向下粗箭头后——>②单击&#xff08;变成粗十字&#xff09;该列——>③拖动选中列 第二步&#xff1a;调…

docker ubuntu tomcat 换源 安装软件

第一种办法参考docker中ubuntu容器更换apt源_ubuntu更改apt源 with dockerfile-CSDN博客 sed -i s/archive.ubuntu.com//mirrors.aliyun.com/g /etc/apt/sources.list sed -i s/security.ubuntu.com//mirrors.aliyun.com/g /etc/apt/sources.list apt update apt install vim…

C++学习Day06之继承中的构造与析构

目录 一、程序及输出1.1 构造、析构顺序1.2 默认构造函数1.3 显示调用父类中的其他构造函数 二、分析与总结 一、程序及输出 1.1 构造、析构顺序 先调用父类构造&#xff0c;再调用其他成员构造&#xff0c; 再调用自身构造 &#xff0c;析构的顺序与构造相反 #include<i…

Linix与Windows上使用nc命令测试某一个服务器端口网络是否正常可访问详细安装及测试步骤

一、windows 1、下载nc安装包 https://nszyf.lanzoum.com/ihtqS0v0lwwh 2、下载后解压放置在自己电脑合适的位置&#xff0c;并且配置到环境变量中 3、配置成功环境变量&#xff0c;winr打开运行&#xff0c;输入cmd&#xff0c;回车&#xff0c;打开一个终端测试 测试成功…

MySQL性能分析1——查看频次

1、查看执行频次 查看当前数据库的INSERT,UPDATE,DELETE,SELECT的访问频次&#xff0c;得到当前数据库是以插入&#xff0c;更新和删除为主还是以查询为主&#xff0c;如果是以插入&#xff0c;更新和删除为主的话&#xff0c;那么优化比重可以轻一点儿。 语法&#xff1a; …

初次安装Android Studio卡在gradle的解决方法

原因 国外的下载的地址无法访问才导致无法下载 解决方案 找到新建项目的保存位置找到gradle文件夹 进入文件夹 用文本打开 如图 大概一样&#xff0c;将国外地址改为国内地址 选中的这一条 国内的地址有 腾讯云提供了 Gradle 的国内镜像&#xff0c;您可以通过访问腾讯云…

300分钟吃透分布式缓存-02讲:如何根据业务来选择缓存模式和组件?

缓存读写模式 如下图&#xff0c;业务系统读写缓存有 3 种模式&#xff1a; & Cache Aside&#xff08;旁路缓存&#xff09; & Read/Write Through&#xff08;读写穿透&#xff09; & Write Behind Caching&#xff08;异步缓存写入&#xff09; Cache Asid…

安装 Windows 10

1.镜像安装 镜像安装:安装Windows 10 2.安装过程(直接以图的形式呈现) 选择专业版的 等待安装即可

Android MMKV 接入+ 替换原生 SP + 原生 SP 数据迁移

背景:项目中一直使用的是原生 SP,众所周知,使用原生 SP 存在卡顿性能问题。公司的性能监控平台抓到不少原生 SP 导致的 ANR 问题: java.io.FileDescriptor.sync (FileDescriptor.java) android.os.FileUtils.sync (FileUtils.java:256) android.app.SharedPreferencesImpl.…

【SpringBoot3】Spring Security 核心概念

一、什么是 Spring Security 注&#xff1a;本文基于Spring Boot 3.2.1 以及 Spring Security 6.2.1 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean&#xff0c;充分利用了…

Vue | (一)Vue核心(下) | 尚硅谷Vue2.0+Vue3.0全套教程

文章目录 &#x1f4da;class与style绑定&#x1f4da;条件渲染&#x1f4da;列表渲染&#x1f407;基本列表&#x1f407;key的原理&#x1f407;列表过滤&#xff08;搜索&#xff09;&#x1f407;列表排序&#x1f407;Vue数据监测 &#x1f4da;收集表单数据&#x1f4da;…

2024/2/18:IO进程线程

作业1&#xff1a;使用fgets统计给定文件的行数 代码&#xff1a; #include <stdio.h> #include <string.h> #include <stdlib.h> int main(int argc, const char *argv[]) {//定义FILE *类型的句柄FILE *fpNULL;//判断是否进行了外部传参if(argc ! 2){pri…

JRT监听-PDF-Excel-Img

依赖全新设计&#xff0c;我们无需再顾虑历史兼容性的束缚&#xff1b;同时&#xff0c;基于多年来累积的深入需求理解&#xff0c;JRT监听机制巧妙地借助CMD命令模式&#xff0c;达成了监听的全面统一。无论是PDF、Excel还是图片文件&#xff0c;都不再需要特殊对待或额外区分…

html的无语义标签:div span

html的无语义标签&#xff1a;div & span 无语义标签&#xff1a;div & span 标题&#xff0c;段落&#xff0c;图片等都是通过固定的标签来表示&#xff0c;标题用h1~h6标签来表示&#xff0c;段落用p标签来表示&#xff0c;图片用img标签来表示……每个标签都有自己…

电商数据分析数据统计数据监控必备-电商API电商数据接口

API&#xff0c;全称Application Programming Interface&#xff0c;是一种用于不同应用程序间通信的接口&#xff0c;它允许不同的应用程序之间交换数据和功能。API可以理解为应用程序提供给其他应用程序或开发者的接口&#xff0c;通过这个接口&#xff0c;其他应用程序或开发…

质量当先:国辰智企QMS产品质量追溯平台助力电子企业发展

在当今竞争激烈的电子产品市场中&#xff0c;质量是企业成功的关键。为了满足客户对高品质产品的需求&#xff0c;企业需要一套可靠的质量管理系统。QMS产品质量追溯平台为电子产品行业提供了全面的解决方案&#xff0c;确保产品质量的可追溯性和持续改进。 产品质量追溯平台是…