目录

Ant Design Pro 后端接口权限按钮系统 

系统架构图

前端实现

权限按钮组件 (AuthButton.tsx)

权限钩子 (useAccess.ts)

权限服务 (permission.ts)

产品列表页面 (ProductList.tsx)

后端接口设计 (Node.js + Express 示例)

权限接口控制器 (permissionController.js)

权限接口路由 (permissionRoutes.js)

数据库模型 (models.js)

权限系统特点

1. 权限等级体系

2. 权限分类

3. 缓存策略

权限管理最佳实践

1. 权限按钮使用示例

2. 权限控制策略

3. 高级权限场景

权限审计与监控


Ant Design Pro 后端接口权限按钮系统 

下面是一个完整的基于后端接口的权限按钮实现方案,包含前端页面、后端接口设计和权限控制系统。

系统架构图

前端实现

权限按钮组件 (AuthButton.tsx)

import React from 'react';
import { Button, ButtonProps, Tooltip } from 'antd';
import { useAccess, Access } from 'umi';
import { hasPermission } from '@/services/permission';
import type { PermissionAction } from '@/services/permission';interface AuthButtonProps extends ButtonProps {/** 权限标识 */permission: string;/** 无权限时提示信息 */noPermissionText?: string;/** 是否隐藏无权限按钮 */hideWhenDisabled?: boolean;/** 是否禁用而非隐藏 */disableWhenNoPermission?: boolean;/** 需要的数据权限上下文 */context?: any;
}const AuthButton: React.FC<AuthButtonProps> = ({permission,noPermissionText = '无操作权限',hideWhenDisabled = true,disableWhenNoPermission = false,context,children,...buttonProps
}) => {const { hasPermission } = useAccess();const hasAuth = hasPermission(permission, context);// 无权限时处理逻辑if (!hasAuth) {// 无权限时需要隐藏按钮if (hideWhenDisabled) return null;// 无权限但不禁用,添加提示const disabledButton = (<Button {...buttonProps} disabled={disableWhenNoPermission}>{children}</Button>);// 根据配置返回禁用按钮或带提示的按钮return disableWhenNoPermission ? (disabledButton) : (<Tooltip title={noPermissionText}>{disabledButton}</Tooltip>);}// 有权限,返回正常按钮return (<Button {...buttonProps}>{children}</Button>);
};export default AuthButton;

权限钩子 (useAccess.ts)

// src/hooks/useAccess.ts
import { useState, useEffect, useCallback } from 'react';
import { getPermissions } from '@/services/permission';type PermissionResult = {hasPermission: (permission: string, context?: any) => boolean;loading: boolean;permissions: string[];refreshPermissions: () => void;
};export default function useAccess(): PermissionResult {const [permissions, setPermissions] = useState<string[]>([]);const [loading, setLoading] = useState(true);// 获取权限数据const fetchPermissions = useCallback(async () => {setLoading(true);try {const res = await getPermissions();setPermissions(res?.permissions || []);} catch (error) {console.error('获取权限失败', error);setPermissions([]);} finally {setLoading(false);}}, []);// 初始化时获取权限useEffect(() => {fetchPermissions();}, [fetchPermissions]);// 检查是否有权限const hasPermission = useCallback((permission: string, context?: any): boolean => {// 如果权限列表包含通配符权限if (permissions.includes('*')) return true;// 精确匹配权限if (permissions.includes(permission)) return true;// 基于数据的权限检查(示例)if (context?.owner === currentUser.id && permissions.includes(`${permission}:own`)) {return true;}return false;}, [permissions]);return {hasPermission,loading,permissions,refreshPermissions: fetchPermissions};
}

权限服务 (permission.ts)

// src/services/permission.ts
import request from 'umi-request';
import type { RequestOptionsInit } from 'umi-request';// 权限类型定义
export type PermissionAction = | 'create' | 'read' | 'update' | 'delete' | 'export' | 'approve' | 'manage' | string;// 权限接口响应格式
export interface PermissionResponse {success: boolean;permissions: string[];
}// 获取当前用户权限
export async function getPermissions(options?: RequestOptionsInit
): Promise<PermissionResponse> {return request('/api/permissions', {method: 'GET',...(options || {}),});
}// 检查特定权限
export async function checkPermission(permission: string, context?: any,options?: RequestOptionsInit
): Promise<{ hasPermission: boolean }> {return request('/api/permissions/check', {method: 'POST',data: { permission, context },...(options || {}),});
}// 权限控制装饰器(用于页面组件)
export function withPermissions(WrappedComponent: React.ComponentType) {return (props: any) => {const { loading, permissions } = useAccess();if (loading) {return (<div style={{ textAlign: 'center', padding: 40 }}><Spin tip="权限验证中..." size="large" /></div>);}if (!permissions.length) {return (<Resultstatus="403"title="403"subTitle="抱歉,您没有访问权限,请联系管理员"/>);}return <WrappedComponent {...props} />;};
}

产品列表页面 (ProductList.tsx)

import React, { useState } from 'react';
import { PageContainer, ProTable } from '@ant-design/pro-components';
import AuthButton from '@/components/AuthButton';
import { PlusOutlined, EditOutlined, DeleteOutlined, ExportOutlined } from '@ant-design/icons';
import type { ProColumns } from '@ant-design/pro-components';
import { Modal, message } from 'antd';
import ProductForm from './ProductForm';interface Product {id: string;name: string;category: string;price: number;stock: number;owner: string;
}const ProductList: React.FC = () => {const [selectedRowKeys, setSelectedRowKeys] = useState<string[]>([]);const [createModalVisible, setCreateModalVisible] = useState(false);const [editRecord, setEditRecord] = useState<Product | null>(null);const columns: ProColumns<Product>[] = [{title: '产品名称',dataIndex: 'name',key: 'name',},{title: '类别',dataIndex: 'category',key: 'category',},{title: '价格',dataIndex: 'price',key: 'price',valueType: 'money',},{title: '库存',dataIndex: 'stock',key: 'stock',renderText: (val: number) => `${val}件`,},{title: '操作',key: 'action',render: (text, record) => (<span><AuthButton type="link" permission="product:update"context={{ owner: record.owner }}onClick={() => handleEdit(record)}><EditOutlined /> 编辑</AuthButton><AuthButton type="link" dangerpermission="product:delete"context={{ owner: record.owner }}noPermissionText="无法删除非本人创建的产品"onClick={() => handleDelete(record)}><DeleteOutlined /> 删除</AuthButton></span>),},];const handleCreate = () => {setCreateModalVisible(true);};const handleEdit = (record: Product) => {setEditRecord(record);};const handleDelete = (record: Product) => {Modal.confirm({title: '确认删除',content: `确定要删除产品【${record.name}】吗?`,onOk: () => {// 调用删除APImessage.success('删除成功');},});};const handleExport = () => {// 导出操作message.success('导出成功');};const handleBatchDelete = () => {Modal.confirm({title: '批量删除',content: `确定要删除选中的${selectedRowKeys.length}个产品吗?`,onOk: () => {// 调用批量删除APImessage.success('批量删除成功');setSelectedRowKeys([]);},});};return (<PageContainer><ProTable<Product>columns={columns}rowKey="id"headerTitle="产品列表"rowSelection={{selectedRowKeys,onChange: setSelectedRowKeys,}}toolBarRender={() => [<AuthButton key="create"type="primary" icon={<PlusOutlined />}permission="product:create"onClick={handleCreate}>新建产品</AuthButton>,<AuthButton key="export"icon={<ExportOutlined />}permission="product:export"onClick={handleExport}>导出数据</AuthButton>,selectedRowKeys.length > 0 && (<AuthButton key="batchDelete"dangerpermission="product:batch-delete"onClick={handleBatchDelete}noPermissionText="无批量删除权限"disableWhenNoPermission>批量删除</AuthButton>)]}request={async (params) => {// 模拟从后端获取产品数据return {data: mockProducts,success: true,total: mockProducts.length,};}}/>{/* 新建/编辑模态框 */}<Modaltitle={editRecord ? "编辑产品" : "新建产品"}open={createModalVisible || !!editRecord}onCancel={() => {setCreateModalVisible(false);setEditRecord(null);}}destroyOnClosefooter={null}><ProductForm initialValues={editRecord}onSuccess={() => {setCreateModalVisible(false);setEditRecord(null);// 刷新表格}}/></Modal></PageContainer>);
};// 模拟产品数据
const mockProducts: Product[] = [{ id: '1', name: 'MacBook Pro', category: 'Laptop', price: 14999, stock: 15, owner: 'user-001' },{ id: '2', name: 'iPhone 14', category: 'Phone', price: 7999, stock: 30, owner: 'user-002' },{ id: '3', name: 'iPad Air', category: 'Tablet', price: 4799, stock: 8, owner: 'user-003' },
];export default ProductList;

后端接口设计 (Node.js + Express 示例)

权限接口控制器 (permissionController.js)

// 后端控制层 - permissionController.js
const db = require('../models');
const { Op } = require('sequelize');class PermissionController {// 获取用户所有权限async getPermissions(req, res) {try {const userId = req.user.id; // 从认证信息中获取用户ID// 1. 获取用户角色const user = await db.User.findByPk(userId, {include: [{model: db.Role,as: 'roles',attributes: ['id', 'name'],through: { attributes: [] }}]});// 2. 获取角色关联的权限const roleIds = user.roles.map(role => role.id);const rolesWithPermissions = await db.Role.findAll({where: { id: { [Op.in]: roleIds } },include: [{model: db.Permission,as: 'permissions',attributes: ['code'],through: { attributes: [] }}]});// 3. 获取用户自定义权限const customPermissions = await db.UserPermission.findAll({where: { userId },include: [{model: db.Permission,attributes: ['code']}]});// 4. 合并权限并去重const permissions = new Set();// 角色权限rolesWithPermissions.forEach(role => {role.permissions.forEach(permission => {permissions.add(permission.code);});});// 自定义权限customPermissions.forEach(up => {permissions.add(up.Permission.code);});res.json({success: true,permissions: Array.from(permissions)});} catch (error) {console.error('获取权限失败', error);res.status(500).json({success: false,message: '获取权限失败'});}}// 检查特定权限async checkPermission(req, res) {try {const userId = req.user.id;const { permission, context } = req.body;// 1. 获取用户所有权限const { permissions } = await this._getAllPermissions(userId);// 2. 检查是否存在完全匹配的权限if (permissions.has(permission) {return res.json({ hasPermission: true });}// 3. 数据权限检查(示例:检查产品所有权)if (permission.startsWith('product:') && context?.productId) {const product = await db.Product.findByPk(context.productId);if (product && product.ownerId === userId) {// 检查拥有者的特殊权限(如 product:update:own)const ownPermission = `${permission}:own`;if (permissions.has(ownPermission)) {return res.json({ hasPermission: true });}}}res.json({ hasPermission: false });} catch (error) {console.error('权限检查失败', error);res.status(500).json({success: false,message: '权限检查失败'});}}// 内部方法:获取用户所有权限async _getAllPermissions(userId) {// ...与getPermissions方法类似// 返回Set对象包含所有权限}
}module.exports = new PermissionController();

权限接口路由 (permissionRoutes.js)

const express = require('express');
const router = express.Router();
const permissionController = require('../controllers/permissionController');
const authMiddleware = require('../middlewares/auth');// 权限认证中间件
router.use(authMiddleware);// 获取用户权限列表
router.get('/permissions', permissionController.getPermissions);// 检查特定权限
router.post('/permissions/check', permissionController.checkPermission);module.exports = router;

数据库模型 (models.js)

module.exports = (sequelize, DataTypes) => {const User = sequelize.define('User', {id: { type: DataTypes.UUID, primaryKey: true },username: DataTypes.STRING,email: DataTypes.STRING,// ...});const Role = sequelize.define('Role', {id: { type: DataTypes.UUID, primaryKey: true },name: DataTypes.STRING,description: DataTypes.STRING});const Permission = sequelize.define('Permission', {id: { type: DataTypes.UUID, primaryKey: true },code: { type: DataTypes.STRING, unique: true },name: DataTypes.STRING,category: DataTypes.STRING,description: DataTypes.TEXT});// 关联关系User.belongsToMany(Role, { through: 'UserRole' });Role.belongsToMany(User, { through: 'UserRole' });Role.belongsToMany(Permission, { through: 'RolePermission' });Permission.belongsToMany(Role, { through: 'RolePermission' });User.belongsToMany(Permission, { through: 'UserPermission' });Permission.belongsToMany(User, { through: 'UserPermission' });return { User, Role, Permission };
};

权限系统特点

1. 权限等级体系

2. 权限分类

权限类型描述示例
功能权限控制操作入口product:create
数据权限控制数据访问范围product:read:department
操作权限控制特定操作order:approve
状态权限控制状态变更order:status:change

3. 缓存策略

// 前端权限缓存机制
const PERMISSION_CACHE_KEY = 'user_permissions';
const CACHE_TTL = 30 * 60 * 1000; // 30分钟async function getPermissionsWithCache() {const cached = localStorage.getItem(PERMISSION_CACHE_KEY);if (cached) {const { permissions, timestamp } = JSON.parse(cached);if (Date.now() - timestamp < CACHE_TTL) {return permissions;}}// 后端获取新权限const res = await getPermissions();const dataToCache = {permissions: res.permissions,timestamp: Date.now()};localStorage.setItem(PERMISSION_CACHE_KEY, JSON.stringify(dataToCache));return res.permissions;
}// 强制刷新
function refreshPermissions() {localStorage.removeItem(PERMISSION_CACHE_KEY);getPermissionsWithCache();
}

权限管理最佳实践

1. 权限按钮使用示例

// 基本按钮
<AuthButton permission="product:create">创建产品</AuthButton>// 带图标和提示的按钮
<AuthButton permission="product:delete"icon={<DeleteOutlined />}noPermissionText="无删除权限"
>删除
</AuthButton>// 数据上下文权限
<AuthButton permission="product:update"context={{ owner: currentUser.id }}
>编辑我的产品
</AuthButton>

2. 权限控制策略

// 页面级别权限控制
const AdminPage = () => {return (<Access permission="system:admin"><div>管理员面板</div>{/* 管理员功能区域 */}</Access>);
};// 条件渲染多个元素
<div><Access permission="reports:view"><DashboardSection /><ReportChart /></Access><Access permission="user:manage"><UserManagementSection /></Access>
</div>

3. 高级权限场景

动态权限加载

const [dynamicPermissions, setDynamicPermissions] = useState(false);useEffect(() => {checkPermission('advanced:feature').then(res => {setDynamicPermissions(res.hasPermission);});
}, []);return (<div>{dynamicPermissions && (<Button>高级功能</Button>)}</div>
);

批量权限检查

const [buttonsEnabled, setButtonsEnabled] = useState({});useEffect(() => {const permissionsToCheck = ['order:create','order:approve','order:export'];checkMultiplePermissions(permissionsToCheck).then(res => {setButtonsEnabled(res);});
}, []);// ...
<Button disabled={!buttonsEnabled['order:create']}>新建订单</Button>

权限审计与监控

// 前端操作日志记录
function logPermissionAction(action: string, hasPermission: boolean, context?: any
) {analytics.track('permission_action', {action,hasPermission,userId: currentUser.id,context,timestamp: new Date().toISOString(),pathname: window.location.pathname});
}// 在权限钩子中调用
const hasPermission = (perm: string, context?: any) => {const hasPerm = /* 权限检查逻辑 */;if (perm.startsWith('sensitive:')) {logPermissionAction(perm, hasPerm, context);}return hasPerm;
};

这个基于 Ant Design Pro 和 TypeScript 的权限按钮系统提供了完整的解决方案:

  1. 前后端分离​:前端基于组件化设计,后端提供灵活的权限服务
  2. 细粒度控制​:支持功能权限和数据权限
  3. 灵活配置​:多种权限控制策略(隐藏、禁用、提示)
  4. 权限缓存​:优化性能减少后端请求
  5. 权限继承​:支持角色权限和直接用户权限
  6. 上下文权限​:支持基于数据所有权的权限检查
  7. 完整审计​:记录敏感操作便于追踪

在企业级项目中,这样的权限系统可以轻松集成到现有架构中,提供安全可靠的权限控制能力。

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

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

相关文章

RAG工程落地:处理文档中表格数据

在 RAG&#xff08;Retrieval-Augmented Generation&#xff09;工程落地过程中&#xff0c;处理文档中的表格数据 是一个非常重要但复杂的问题&#xff0c;特别是针对技术文档、报告、论文等结构化强的资料。比如PDF文档里的表格数据&#xff0c;如下&#xff1a; RAG处理表格…

大模型在肺癌预测及个性化诊疗方案中的应用研究

目录 一、引言 1.1 研究背景与意义 1.2 研究目的与创新点 1.3 国内外研究现状 二、大模型预测肺癌的原理与方法 2.1 大模型概述 2.2 数据收集与预处理 2.3 特征工程 2.4 模型训练与优化 三、术前预测与方案制定 3.1 病情评估 3.1.1 肿瘤大小、位置及分期预测 3.1.…

如何高效分享WordPress博客文章

在当今信息过载的时代&#xff0c;写好一篇优秀的 WordPress 博客文章只是起点&#xff0c;如何有效地分享给更多读者才是成功的关键所在。对于新手用户而言&#xff0c;选择合适的工具和平台尤为重要。现在许多服务器提供商支持一键安装WordPress功能&#xff0c;比如 Hosteas…

以孝治家有机农业生态文明考察组赴邯郸心田农场考察学习

按照2025年中共中央、国务院印发了关于《乡村全面振兴规划&#xff08;2024—2027年&#xff09;》的战略部署。根据《乡村全面振兴规划》提出的“坚持人与自然和谐共生。牢固树立和践行绿水青山就是金山银山的理念&#xff0c;落实节约优先、保护优先、自然恢复为主的方针&…

解决el-input无法输入的问题 vue2+element el-input

问题描述: 在el-dialog中el-form组件来做表单提交 中文输入模式: 在初次输入的时候能输入内容 但是再次输入无法更改内容 英文输入模式: 只能输入一个英文 很多文章都是说 是双向绑定的问题 但是我仔细看了 变量的双向绑定确实没毛病 直到我发现了是因为我el-input中的图…

16_集成学习

描述 集成学习&#xff08;Ensemble Learning&#xff09;是一种通过结合多个模型的预测结果来提高整体性能的技术。集成学习的核心思想是通过多个弱学习器的组合&#xff0c;可以构建一个强学习器。 sklearn中常见的集成学习算法&#xff1a; Bagging&#xff1a;通过自助采…

学习STC51单片机43(芯片为STC89C52RCRC)智能小车9(语音识别小车)

每日一言 不必与他人比较速度&#xff0c;你走的每一步都在书写自己的传奇。 案例&#xff1a;语音识别小车 这个是最后一个功能了&#xff0c;其实就是用语音功能让小车自己切换各种模式&#xff0c;当然了我们需要先学习一下语音模块 硬件&#xff1a;SU-03T 这个叫做非特定…

Android 中 解析 XML 字符串的几种方式

在 Android 开发中&#xff0c;解析 XML 文件有多种方式&#xff0c;每种方式都有其特点和适用场景。常见的 XML 解析方式有 DOM 解析、SAX 解析 和 XmlPullParser 解析。 1、DOM 解析 DOM&#xff08;Document Object Model&#xff09;解析是一种基于树结构的解析方式&#…

云端算力革命:川翔云电脑如何重新定义创作自由

在设计与科技深度融合的时代&#xff0c;高性能硬件的桎梏正成为创意释放的最大障碍。川翔云电脑以云端算力为支点&#xff0c;通过弹性算力、高效存储、多端接入三大核心优势&#xff0c;让顶级 GPU 资源触手可及。 一、核心优势&#xff1a;突破物理极限的云端工作站 弹性算…

1.容器技术与docker环境部署

一&#xff1a;docker概述 因为 Docker 轻便、快速的特性&#xff0c;可以使应用达到快速迭代的目的。每次小的变更&#xff0c;马上就可以看到效果&#xff0c;而不用将若干个小变更积攒到一定程度再变更。每次变更一小部分其实是一种非常安全的方式&#xff0c;在开发环境中…

关于 RSA:RSA 加密算法过程

RSA 是一种非对称加密算法&#xff0c;用“公钥”加密&#xff0c;用“私钥”解密&#xff0c;保证数据传输安全。 比喻理解&#xff1a;锁和钥匙 想象一下&#xff1a; 公钥是“上锁的锁”&#xff0c;别人可以用它锁住箱子&#xff08;加密&#xff09;&#xff0c;但打不开…

SM3算法C语言实现(无第三方库,带测试)

一、SM3算法介绍 SM3算法是中国国家密码管理局&#xff08;OSCCA&#xff09;于2010年发布的商用密码散列函数标准&#xff0c;属于我国自主设计的密码算法体系之一 &#xff0c;标准文档下载地址为&#xff1a;SM3密码杂凑算法 。SM3算法输出长度为256位&#xff08;32字节&a…

搜索二叉数(c++)

前言 在学习数据结构的时候我们学习过二叉树&#xff0c;那啥是搜索二叉树呢&#xff1f;我们知道单纯的二叉树没有增删查改的实际意义&#xff0c;因为没有任何限制条件的二叉树其实用处很局限。但是堆就不一样了&#xff0c;他就是一个二叉树加上了大小堆的限制条件&#xf…

vc MFC在opencv的Mat图像上显示中文:Mat转位MFC的CImage,画图写文字,再转回Mat

vc MFC在opencv的Mat图像上显示中文&#xff1a;Mat转位MFC的CImage&#xff0c;画图写文字&#xff0c;再转回Mat // Step 1 创建CImage获取dc int iImgW matImgSized.cols; int iImgH matImgSized.rows; int iChannel matImgSized.channels(); bool bCon matImgSized.is…

Docker环境部署

目录 一&#xff1a;Docker 概述 1.什么是 Docker 2:Docker 的优势 3.Docker 的应用场景 4:Docker 核心概念 二:Docker 安装 1:本安装方式使用阿里的软件仓库 三:Docker 镜像操作 1:获取镜像 2.查看镜像信息 3.查看镜像详细信息 4.修改镜像标签(老名字新名字) 5:删…

Axios 拦截器实现原理深度剖析:构建优雅的请求处理管道

在构建现代前端应用时&#xff0c;网络请求处理是关键环节。作为最流行的HTTP客户端库之一&#xff0c;Axios通过其拦截器机制&#xff08;Interceptors&#xff09;提供了强大的请求/响应处理能力。本文将深入Axios源码&#xff0c;揭示拦截器背后的精妙设计与实现原理。 一、…

宝塔安装nginx-http-flv-module,音视频直播,第二篇

1&#xff0c;先安装环境安装nginx 先卸载原有nigix nigix 大于等于 1.2.6 cd /www/server # 进入宝塔目录 yum install git -y git clone https://gitee.com/winshining/nginx-http-flv-module.git 使用源码安装nigix 在 自定义模块 区域点击「添加」&#xff0c;填写以下参…

低延迟4G专网:保障关键业务的实时通信

在工业互联网、智慧园区、应急通信等对“实时性”要求极高的场景中&#xff0c;网络延迟的高低&#xff0c;直接决定了业务运行的可靠性与安全性。IPLOOK依托多年核心网研发经验&#xff0c;推出的低延迟4G专网解决方案&#xff0c;正是为此类关键业务打造的“通信专线”&#…

NLP语言发展路径分享

自然语言处理初期发展历程 早期&#xff1a;离散表示 one-hot&#xff08;只表达“有/无”&#xff0c;语义完全丢失&#xff09;→ n-gram&#xff08;局部上下文&#xff0c;但高维稀疏&#xff09;→ TF-IDF&#xff08;考虑词频与权重&#xff0c;但不能表达词关联&#x…

如何将文件从安卓设备传输到电脑?

将文件从 Android 手机传输到 PC 是例行公事吗&#xff1f;想让文件传输更轻松吗&#xff1f;幸运的是&#xff0c;您可以从本文中获得 7 种方法&#xff0c;其中包含详细的步骤&#xff0c;帮助您轻松了解如何将文件从 Android 传输到 PC&#xff0c;涵盖了从无线工具到传统 U…