当前位置: 首页 > news >正文

DBAPI 实现不同角色控制查看表的不同列

DBAPI 实现不同角色控制查看表的不同列

场景说明

在数据库管理系统中,对表进行列级别的权限控制是一项关键的安全措施,特别是在处理敏感数据或需要遵守特定数据访问控制策略的情况下。合理的列权限控制不仅能保护敏感信息,还能帮助组织满足合规性要求。

以下是一些典型的应用场景:

敏感数据保护

当表中包含敏感信息(如个人身份信息、财务数据、医疗记录等)时,通过列权限控制,只允许特定角色或用户访问这些列,可以有效防止数据泄露,降低数据安全风险。

合规性要求

某些行业或地区有严格的数据保护法规(如 GDPR、HIPAA 等),要求对敏感数据的访问进行严格控制。列权限控制可以帮助组织满足这些合规性要求,避免因数据泄露而面临的法律风险。

数据分层访问

在大型企业中,不同部门或用户角色可能只需要访问表中的部分列。通过列权限控制,可以确保用户只能访问其工作所需的列,实现最小权限原则,减少不必要的数据访问风险。

实现方案

DBAPI 提供了 API 编排、动态 SQL、数组传参的功能,通过这些功能,可以实现列权限控制。
为了实现列权限可以动态配置,我们采用以下方案:

  1. 动态权限配置:在数据库中维护一张权限配置表,用于配置不同用户可以访问的列,便于权限信息的动态修改。
  2. API 编排实现:创建两个独立的 API,并通过编排顺序执行。第一个 API 查询用户拥有的权限列,第二个 API 根据这些权限列查询表数据。

实施示例

1. 创建商品信息表

首先准备一张商品信息表 products,包含以下列:

字段名类型说明
idint商品 ID
namevarchar商品名称
descriptiontext商品描述
categoryvarchar商品分类
costdecimal进货成本(敏感数据)
suppliervarchar供应商(敏感数据)

示例数据如下:

idnamedescriptioncategorycostsupplier
1iPhone 13 Pro高性能手机手机9999apple
2MacBook Pro性能 Strong电脑19999apple
3Mate 60高性能手机手机6999华为

其中,商品的进货成本 cost 列和供应商 supplier 列为保密数据,需要根据用户的角色进行权限控制。

2. 创建权限配置表

创建权限配置表 permission_config,用于记录用户对表列的权限信息:

字段名类型说明
user_idbigint用户 ID
table_namevarchar表名
column_namevarchar列名

示例数据如下:

user_idtable_namecolumn_name
1productscost
1productssupplier
2productssupplier

3. 创建查询用户权限列的 API

创建 API,配置参数 userid,类型为 bigint,SQL 查询语句如下:

SELECT column_name FROM permission_config WHERE user_id = #{userid} and table_name = 'products'

API配置界面
参数配置界面

该 API 用于获取指定用户有权访问的所有列名。

数据格式转换

配置完成后,我们进行请求测试,发现返回的数据格式为:

{"data": [{ "column_name": "cost" }, { "column_name": "supplier" }],"msg": null,"success": true
}

测试结果

但实际上我们期望的数据格式是简洁的数组形式:["cost", "supplier"]

为了实现这一目标,我们需要对 API 返回的数据进行格式转换。在 API 配置中找到"全局插件 - 数据转换"选项,填写以下 Groovy 脚本:

data.data.collect { it.column_name }

这段 groovy 代码的意思是将返回的数据中的 data 属性进行循环, 提取每个元素的column_name 字段,并返回一个包含这些提取值的数组。

并将脚本语言选择为 Groovy

数据转换配置

配置完成后保存 API,并再次进行请求测试。可以看到返回的数据格式已经转换为我们期望的数组形式:

转换后测试结果

通过这样的数据转换处理,我们成功将原始的复杂 JSON 结构简化为便于后续处理的字符串数组格式,为下一步的数据查询操作提供了便利。

4. 创建查询表数据的 API

创建 API,配置参数 authedColumns,类型为 Array<string>,SQL 查询语句如下:

SELECT name, description,
<foreach collection="authedColumns" item="column" separator=",">${column}
</foreach>
FROM products

SQL配置界面
参数配置界面

注意事项:

  • 使用 <foreach> 标签遍历 authedColumns 数组,将每个列名拼接成 SQL 语句中要查询的列名
  • 必须使用 ${column} 来动态替换列名,不能使用 #{column}

请求测试 API,可以看到 API 正常返回数据:

测试结果

5. 创建编排 API

按照以下步骤创建编排 API:

步骤 1:配置基础参数

创建编排 API,配置参数 userid,类型为 bigint

基础参数配置
参数详情

步骤 2:添加开始节点

点击添加开始节点,作为流程的起点:

开始节点

步骤 3:添加权限查询节点
  1. 点击添加 API 节点,编辑 API 节点,选择第一个 API(查询用户权限列)
  2. 配置参数 useridparameters.userid
  3. 配置节点 ID 为 getAuthedColumns

parameters 表示整个 API 的参数,parameters.userid 表示取参数 userid 的值

添加API节点
节点配置

步骤 4:添加数据查询节点
  1. 点击添加 API 节点,选择第二个 API(查询表数据)
  2. 配置参数 authedColumnsresults.getAuthedColumns
  3. 配置节点 ID 为 getData

results 表示所有 API 节点的返回结果,results.getAuthedColumns 表示取第一个 API 的返回结果

添加数据查询节点
节点参数配置

步骤 5:添加结束节点
  1. 点击添加结束节点
  2. 配置数据脚本为 results.getData.data

results 表示所有 API 节点的返回结果,results.getData.data 表示取第二个 API 的返回结果中的 data 字段的值

结束节点配置1
结束节点配置2

步骤 6:连接节点

使用连线将所有节点按顺序连接起来:开始节点 → getAuthedColumns 节点 → getData 节点 → end 节点

最后点击保存并发布编排 API:

完整流程图

预期效果

通过以上配置,不同用户将看到不同的数据列:

  • 用户 1:可以查看 costsupplier

用户1效果

  • 用户 2:只能查看 supplier

用户2效果

这种实现方式既保证了数据的安全性,又提供了灵活的权限管理机制。

总结与优化

处理空列权限的 SQL 语法问题

对于第二个 API(查询表数据的 API),当某个用户没有可访问的敏感列权限时,会生成如下 SQL 语句:

SELECT name, description, FROM products

SQL语法错误

这个 SQL 语句存在语法错误(末尾多余的逗号),会导致查询执行失败。

解决方案

DBAPI 提供了类似 MyBatis 的动态 SQL 功能,其中的 trim 标签可以优雅地解决这个问题。修改后的 SQL 如下:

SELECT
<trim prefix="" suffix="" suffixesToOverride="," prefixesToOverride="">name, description,<foreach collection="authedColumns" item="column" separator=",">${column}</foreach>
</trim>
FROM products

优化后的SQL配置

trim 标签详解

trim 标签是 DBAPI 中一个强大的动态 SQL 处理工具,其主要属性包括:

  • prefix:在包裹内容前添加指定前缀
  • suffix:在包裹内容后添加指定后缀
  • suffixesToOverride:指定需要去除的后缀字符
  • prefixesToOverride:指定需要去除的前缀字符

在这个场景中,我们将 suffixesToOverride 属性设置为逗号,,表示当 trim 标签包裹的内容以逗号结尾时,会自动去除结尾的逗号,从而避免 SQL 语法错误。

这种动态 SQL 处理机制确保了无论用户拥有多少列权限,生成的 SQL 语句都是语法正确的,大大提高了系统的健壮性和用户体验。

根据客户端身份获取权限

基于用户ID参数获取权限存在安全风险,客户端可能通过修改userid参数获取未授权的数据。更安全的做法是根据客户端身份(clientId)来确定数据访问权限。

1. 创建并配置客户端

首先创建两个客户端并授权其访问相应的API分组:

创建客户端1
授权客户端

2. 调整权限配置表结构

修改权限配置表 permission_config,使用client_id替代user_id来配置列权限:

字段名类型说明
client_idvarchar客户端 ID
table_namevarchar表名
column_namevarchar列名

示例数据:

client_idtable_namecolumn_name
CMlWBCb0v7U3goZGproductscost
CMlWBCb0v7U3goZGproductssupplier
hTAOTQ5DmEb7IXMQproductssupplier
3. 更新权限查询API

调整权限查询API配置:

  • 移除userid参数
  • 将API权限设置为私有
  • 更新SQL语句使用系统内置变量__clientId
SELECT column_name FROM permission_config 
WHERE client_id = #{__clientId} and table_name = 'products'

API SQL配置
API权限设置

提示:SQL中可直接使用系统内置变量__clientId获取当前请求的客户端ID。

4. 验证权限控制效果

使用不同客户端访问API,会得到不同的数据列权限:

客户端1访问结果
客户端2访问结果

注意:访问私有API必须携带有效的token,系统通过token识别客户端身份。

http://www.dtcms.com/a/324114.html

相关文章:

  • 量子计算机实用化:从理论到现实的艰难跨越
  • 数据中心可视化:算力中枢智能运维
  • 编程基础之字符串——统计数字字符个数
  • JDBC的连接过程(超详细)
  • 【Docker-Day 12】揭秘容器网络:深入理解 Docker Bridge 模式与端口映射
  • Python爬虫-爬取政务网站的文档正文内容和附件数据
  • 【Linux | 网络】数据链路层
  • 电脑清理3步速成法
  • 三相LLC拓扑分析
  • CompletableFuture实现Excel sheet页导出
  • 产品经理入门 - 产品解决方案(需求分析、 功能优先级划分、功能价值、用户体验)
  • RabbitMQ面试精讲 Day 19:网络调优与连接池管理
  • NLP---IF-IDF案例分析
  • AI编程插件对比分析:CodeRider、GitHub Copilot及其他
  • 构建企业级Odoo 18 WMS——功能、架构与拓展蓝图
  • 宝塔面板部署sentinel
  • 【传奇开心果系列】基于Flet框架开发的增强版“Hello World“应用程序学习flet框架的拔高起点
  • 【后端】Java 8 特性 `User::getId` 语法(方法引用)介绍
  • Linux常用命令(后端开发版)
  • SQL(结构化查询语言)的四大核心分类
  • 【后端】Java 8 特性 Optional 可选类 介绍
  • Oracle 19C 查看卡慢的解决思路
  • Spring Boot整合knife4j实战
  • iceberg安装部署
  • imx6ull支持4G模块
  • C++高频知识点(十八)
  • 生产环境中Spring Cloud Sleuth与Zipkin分布式链路追踪实战经验分享
  • 咪咕MGV3200-KLH_GK6323V100C_板号E503744_安卓9_短接强刷包-可救砖
  • uni-app 网络请求终极选型:uni.request、axios、uni-network、alova 谁才是你的真命请求库?
  • CD64.【C++ Dev】多态(3): 反汇编剖析单继承下的虚函数表