开箱即用的GO后台管理系统 Kratos Admin - 前端权限控制

简介: Kratos Admin 是一个开箱即用的 GO 后台管理系统,前端权限管理分为路由和按钮权限。路由权限支持后端动态生成和前端固定配置两种方式,通过 `.env` 文件配置 `VITE_ROUTER_ACCESS_MODE` 实现。按钮权限可通过权限码或角色控制,支持组件、API 和指令三种方式。项目代码托管于 Gitee 和 Github。

开箱即用的GO后台管理系统 Kratos Admin - 前端权限控制

前端的权限归属于:功能权限。根据功能控制的细粒度,前端的权限主要分为两个部分:

  1. 页面级权限;
  2. 按钮级权限。

页面级权限

页面级权限,我们可以通过菜单隐藏、路由拦截来实现。在实际应用中,从而我们就可以控制用户能否进入 “财务报表”“人事管理” 等页面。

路由的控制方式分为两种方式:

  1. 后端控制;
  2. 前端控制。

后端访问控制

  • 实现原理: 通过调用后端的接口,获取到一个遵循一定的数据结构的路由配置数据,前端拿到路由配置数据后,根据需要将该数据处理为可识别的结构,再通过 router.addRoute 添加到路由实例,实现页面权限的动态控制。

  • 缺点: 后端需要提供符合规范的数据,前端相应的还需要需要处理数据,开发维护起来比较复杂,所以它也只适合权限较为复杂的系统。

前端启用办法,修改.env配置文件VITE_ROUTER_ACCESS_MODE的值为backend

# 路由的访问模式:frontend,backend
VITE_ROUTER_ACCESS_MODE=backend

前端的核心代码在src/router/access.ts

async function generateAccess(options: GenerateMenuAndRoutesOptions) {
   
  ...

  return await generateAccessible(preferences.app.accessMode, {
   
    ...options,
    fetchMenuListAsync: async () => {
   
      message.loading({
   
        content: `${
     $t('common.loadingMenu')}...`,
        duration: 1.5,
      });
      const data = (await defRouterService.ListRoute({
   })) ?? [];
      return data.items ?? [];
    },
    ...
  });
}

前端访问控制

  • 实现原理: 在前端固定写死路由的权限,指定路由有哪些权限可以查看。只初始化通用的路由,需要权限才能访问的路由没有被加入路由表内。在登录后或者其他方式获取用户角色后,通过角色去遍历路由表,获取该角色可以访问的路由表,生成路由表,再通过 router.addRoute 添加到路由实例,实现权限的过滤。

  • 缺点: 权限相对不自由,如果后台改动角色,前台也需要跟着改动,并且改动的工作量还不小。适合角色较固定的系统。

前端启用办法,修改.env配置文件VITE_ROUTER_ACCESS_MODE的值为frontend

# 路由的访问模式:frontend,backend
VITE_ROUTER_ACCESS_MODE=frontend

然后,我们需要在本地的固定路由里面写入authority字段,里边填写的是后端配置的角色码,如果该字段不填写,则为所有人可见,如果为字段数据为空,则为所有人不可见:

const system: RouteRecordRaw[] = [
 {
   
    path: '/system',
    name: 'System',
    ...
    meta: {
   
      authority: ['super'],
      ...
    },
  },
];

根据src/store/auth里面的代码显示:

// 设置登录用户信息,需要确保 userInfo.roles 是一个数组,且包含路由表中的权限
// 例如:userInfo.roles=['super', 'admin']
authStore.setUserInfo(userInfo);

所以,我们需要在用户的数据里面加入一个roles的字段,该字段为角色码列表,将其传递给前端:

message User {
    repeated string roles;
}

菜单可见,但禁止访问

有时候,我们需要菜单可见,但是禁止访问,可以通过下面的方式实现,设置 menuVisibleWithForbiddentrue,此时菜单可见,但是禁止访问,会跳转403页面。

{
   
    meta: {
   
      menuVisibleWithForbidden: true,
    },
},

按钮级权限

在某些情况下,我们需要对按钮进行最为细粒度的控制,我们可以借助 权限码(Permission Code)或者 角色码(Role Code)来控制按钮的显示。

权限码

权限码是系统中最小粒度的权限标识,用于唯一标记某个具体的操作权限或资源访问权限。它通常以字符串(如user:add、order:delete)或数值形式存在,代表用户可以执行的单个操作或访问的单个资源。

权限码为接口返回的权限码,通过权限码来判断按钮是否显示,逻辑在src/store/auth下:

// 获取用户信息并存储到 accessStore 中
const [fetchUserInfoResult, accessCodes] = await Promise.all([
    fetchUserInfo(),
    fetchAccessCodes(),
]);

userInfo = fetchUserInfoResult;

userStore.setUserInfo(userInfo);
accessStore.setAccessCodes(accessCodes.codes);

/**
 * 拉取用户信息
 */
async function fetchUserInfo() {
   
    return (await defAuthnService.GetMe({
    id: 0 })) as UserInfo;
}

/**
 * 获取用户权限码
 */
async function fetchAccessCodes() {
   
    return await defRouterService.ListPermissionCode({
   });
}

我们只需要调用fetchAccessCodes方法便可以拥有权限码,权限码返回的数据结构为字符串数组,例如:['product:add', 'product:edit', 'order:refund', 'account:query']

有了权限码,就可以使用 @vben/access 提供的AccessControl组件及API来进行按钮的显示与隐藏。

组件方式

<script lang="ts" setup>
import {
    AccessControl } from '@vben/access';
</script>

<template>
  <!-- 需要指明 type="code" -->
  <AccessControl :codes="['product:add']" type="code">
    <Button> 添加商品 ["product:add"] </Button>
  </AccessControl>
  <AccessControl :codes="['product:edit']" type="code">
    <Button> 编辑商品 ["product:edit"] </Button>
  </AccessControl>
</template>

API方式

<script lang="ts" setup>
import {
    useAccess } from '@vben/access';

const {
    hasAccessByCodes } = useAccess();
</script>

<template>
  <Button v-if="hasAccessByCodes(['product:add'])">
    添加商品 ["product:add"]
  </Button>
  <Button v-if="hasAccessByCodes(['product:edit'])">
    编辑商品 ["product:edit"]
  </Button>
</template>

指令方式

指令支持绑定单个或多个权限码。单个时可以直接传入字符串或数组中包含一个权限码,多个权限码则传入数组。

<template>
  <Button class="mr-4" v-access:code="'product:add'">
    添加商品 ["product:add"]
  </Button>
  <Button class="mr-4" v-access:code="['product:edit']">
    编辑商品 ["product:edit"]
  </Button>
</template>

角色码

角色码所依赖的数据是:useUserStore里的userRoles

import {
    useUserStore } from '@vben/stores';

const userStore = useUserStore();

function hasAccessByRoles(roles: string[]) {
   
  const userRoleSet = new Set(userStore.userRoles);
  const intersection = roles.filter((item) => userRoleSet.has(item));
  return intersection.length > 0;
}

它是通过调用下面这个方法拉取到角色码:

async function fetchUserInfo() {
   
    return (await defAuthnService.GetMe({
    id: 0 })) as UserInfo;
}

再调用下面的代码保存到本地:

// 设置角色信息
const roles = userInfo?.roles ?? [];
this.setUserRoles(roles);

组件方式

<script lang="ts" setup>
import {
    AccessControl } from '@vben/access';
</script>

<template>
  <AccessControl :codes="['super']" type="role">
    <Button> Super 角色可见 </Button>
  </AccessControl>
  <AccessControl :codes="['admin']" type="role">
    <Button> Admin 角色可见 </Button>
  </AccessControl>
  <AccessControl :codes="['user']" type="role">
    <Button> User 角色可见 </Button>
  </AccessControl>
  <AccessControl :codes="['super', 'admin']" type="role">
    <Button> Super & Admin 角色可见 </Button>
  </AccessControl>
</template>

API方式

<script lang="ts" setup>
import {
    useAccess } from '@vben/access';

const {
    hasAccessByRoles } = useAccess();
</script>

<template>
  <Button v-if="hasAccessByRoles(['super'])"> Super 账号可见 </Button>
  <Button v-if="hasAccessByRoles(['admin'])"> Admin 账号可见 </Button>
  <Button v-if="hasAccessByRoles(['user'])"> User 账号可见 </Button>
  <Button v-if="hasAccessByRoles(['super', 'admin'])">
    Super & Admin 账号可见
  </Button>
</template>

指令方式

指令支持绑定单个或多个角色。单个时可以直接传入字符串或数组中包含一个角色,多个角色均可访问则传入数组。

<template>
  <Button class="mr-4" v-access:role="'super'"> Super 角色可见 </Button>
  <Button class="mr-4" v-access:role="['super']"> Super 角色可见 </Button>
  <Button class="mr-4" v-access:role="['admin']"> Admin 角色可见 </Button>
  <Button class="mr-4" v-access:role="['user']"> User 角色可见 </Button>
  <Button class="mr-4" v-access:role="['super', 'admin']">
    Super & Admin 角色可见
  </Button>
</template>

项目代码

参考资料

目录
相关文章
|
3月前
|
前端开发 JavaScript Go
开箱即用的GO后台管理系统 Kratos Admin - 介绍
这是一个前后端分离的中台、后台,后端基于go、go-kratos、ent、gorm等,前端基于vue3、ts、Antdv、Vben开发。支持多租户、数据权限、动态Api、任务调度、OSS文件上传、滑块拼图验证、国内外主流数据库自由切换和动态高级查询。集成统一认证授权、事件总线、国际化、数据验证、分布式缓存、分布式事务、Ip限流、全Api鉴权、集成测试、性能分析、健康检查、接口文档等。
390 1
开箱即用的GO后台管理系统 Kratos Admin - 介绍
|
7月前
|
SQL JSON 关系型数据库
开箱即用的GO后台管理系统 Kratos Admin - 列表查询规则
Kratos Admin 是一个开箱即用的GO后台管理系统,支持通用列表查询请求。通过 `page`、`pageSize`、`query`(AND过滤)、`or`(OR过滤)、`orderBy`(排序)、`noPaging`(不分页)和 `fieldMask`(字段掩码)等参数,灵活配置查询条件。过滤规则遵循Python ORM风格,支持多种查找类型如 `in`、`gte`、`icontains` 等,适用于不同数据库。
101 0
|
4月前
|
前端开发 JavaScript 安全
7.6K Star Shadcn Admin:颜值与实力并存的后台管理系统,前端开发者的新宠!
"基于 Shadcn UI 和 Vite 打造的现代化管理后台,开箱即用的响应式设计 + 无障碍访问,让后台开发从未如此优雅!" —— 来自 GitHub 7.6K 星认证
851 26
|
3月前
|
JSON 前端开发 Java
开箱即用的GO后台管理系统 Kratos Admin - 交互式API文档 Swagger UI
Kratos Admin 集成 Swagger UI,实现交互式 API 文档。通过 Buf 生成 OpenAPI 规范,并内嵌至服务,自动同步接口变动,提升调试与协作效率。
138 1
开箱即用的GO后台管理系统 Kratos Admin - 交互式API文档 Swagger UI
|
3月前
|
前端开发 安全 Go
开箱即用的GO后台管理系统 Kratos Admin - 如何上传文件
Kratos Admin 是一个开箱即用的 Go 语言后台管理系统,支持通过 MinIO 实现高效文件上传。系统提供两种上传方式:一是通过预签名 URL 直接上传至 MinIO,减轻服务压力;二是通过 Kratos 微服务中转上传。前者推荐使用,具备安全、高效、易扩展等优点。文章详细介绍了两种方式的实现代码及前后端交互流程,并附有完整项目源码供参考。
102 2
|
3月前
|
JSON Cloud Native Go
开箱即用的GO后台管理系统 Kratos Admin - 后端权限控制
后端的权限控制主要分为两种: API权限控制; 数据权限控制。 在本文,我们不讨论数据权限的控制,主要讲API的权限控制。
156 1
|
3月前
|
JSON 前端开发 API
开箱即用的GO后台管理系统 Kratos Admin - API管理
Protobuf具有序列化后数据量更小、序列化/反序列化速度更快、更简单的特性;而JSON则相反,序列化后数据量较大,序列化和反序列化速度不优的特性,但是前端对JSON是原生支持,对前端极其友好。那么,我们可以在服务之间使用gRPC进行通讯,服务与前端之间可以通过RESTfull进行通讯。
92 0
|
9月前
|
SpringCloudAlibaba JavaScript Dubbo
【SpringCloud Alibaba系列】Dubbo dubbo-admin安装教程篇
本文介绍了 Dubbo-Admin 的安装和使用步骤。Dubbo-Admin 是一个前后端分离的项目,前端基于 Vue,后端基于 Spring Boot。安装前需确保开发环境(Windows 10)已安装 JDK、Maven 和 Node.js,并在 Linux CentOS 7 上部署 Zookeeper 作为注册中心。
2546 1
【SpringCloud Alibaba系列】Dubbo dubbo-admin安装教程篇
|
存储 安全 Linux
Podman入门全指南:安装、配置与运行容器
Podman入门全指南:安装、配置与运行容器
7103 1
|
10月前
|
存储 NoSQL 关系型数据库
微服务Zipkin链路追踪原理,图解版,一文吃透!
本文重点讲解Zipkin链路追踪的原理与使用,帮助解决微服务架构下的服务响应延迟等问题,提升系统性能与稳定性。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
微服务Zipkin链路追踪原理,图解版,一文吃透!