当前位置: 首页 > 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.xdnf.cn/news/1274725.html

相关文章:

  • SQL约束:数据完整性的守护者
  • 【面试场景题】异地多活改造方案
  • 实现两个开发板的串口通讯(基于STC8实现)
  • Oracle lgwr触发条件
  • c语言常见错误
  • 深入解析微服务分布式事务的原理与优化实践
  • 【代码随想录day 16】 力扣 513.找树左下角的值
  • Linux 路由子系统深度分析:框架、实现与代码路径
  • MariaDB 数据库管理
  • 活动策划(展会、年会),在线工具能快速出邀请函不?
  • Python 实例属性和类属性
  • 为wordpress顶部header.php文件中调用不同的标题和摘要
  • H3C(基于Comware操作系统)与eNSP平台(模拟华为VRP操作系统)的命令差异
  • Shell脚本-了解i++和++i
  • 堆(Java实现)
  • Spark学习(Pyspark)
  • 整数规划-分支定界
  • 【软件测试】BUG篇 — 详解
  • ATF(TF-A)安全通告 TFV-13(CVE-2024-7881)
  • 33.搜索旋转排序数组
  • ECharts 的理解和简单应用笔记
  • Gin vs Beego vs Echo:三大主流 Go Web 框架深度对比
  • 使用Blender可视化多传感器坐标系转换
  • sqli-labs-master/Less-51~Less-61
  • 文件 IO
  • MySQL 子查询
  • 大模型时代的机器人研究趋势:从多模态融合到高效迁移
  • Flutter 与 Android NDK 集成实战:实现高性能原生功能
  • wordpress文章摘要调用的3种方法
  • AI(1)-神经网络(正向传播与反向传播)