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

权限即数据:企业系统中的字段级访问控制架构实战(β=0.6)

摘要

这篇文章介绍了一个企业系统中的字段权限解析方案,通过规则表与命中记录表(biz_rule_hit)联动,实现对业务数据的动态权限控制。流程包括替换用户上下文变量、记录命中规则、查询业务数据并关联命中信息,最终在内存中合并字段权限等级(editable/view/masked/hidden),返回前端使用。该方案支持多规则叠加、权限优先级合并,并实现前后端解耦,适用于复杂权限场景的可审计、可扩展设计。
规则表 + biz_rule_hit → JOIN 业务表 → 内存生成字段权限 → 返回前端,并且处理四种权限(editable/view/masked/hidden)逗号分割字段

下面用 Java + 数据库 的完整示例:


1️⃣ 数据库:统一规则命中表

CREATE TABLE biz_rule_hit (biz_table_name VARCHAR(128) NOT NULL,  -- 业务表名biz_id INT NOT NULL,                   -- 业务表主键rule_id INT NOT NULL,                  -- 命中规则IDuser_id INT NOT NULL,                  -- 用户IDhit_time DATETIME DEFAULT GETDATE(),PRIMARY KEY (biz_table_name, biz_id, rule_id, user_id)
);
  • 一张表管理所有业务表的命中记录
  • biz_table_name 区分业务表

2️⃣ 读取规则表(替换用户上下文变量 + 解析字段)

class Rule {int ruleId;String evaluatedCondition;      // 替换后的 SQL 条件List<String> editable;List<String> view;List<String> masked;List<String> hidden;
}int userId = 123;
int deptId = 10;
String bizTable = "biz_table";List<Rule> rules = jdbcTemplate.query("SELECT rule_id, condition_sql, editable, view, masked, hidden FROM rule_table WHERE biz_table = ? ORDER BY priority ASC",new Object[]{bizTable},(rs, rowNum) -> {Rule r = new Rule();r.ruleId = rs.getInt("rule_id");r.evaluatedCondition = rs.getString("condition_sql").replace("@UserID", String.valueOf(userId)).replace("@DeptID", String.valueOf(deptId));r.editable = Arrays.asList(rs.getString("editable").split(","));r.view     = Arrays.asList(rs.getString("view").split(","));r.masked   = Arrays.asList(rs.getString("masked").split(","));r.hidden   = Arrays.asList(rs.getString("hidden").split(","));return r;}
);

3️⃣ 写入 biz_rule_hit 命中表

// 先删除该用户该业务表旧记录
jdbcTemplate.update("DELETE FROM biz_rule_hit WHERE user_id = ? AND biz_table_name = ?", userId, bizTable);// 插入命中记录
StringBuilder sqlInsertHits = new StringBuilder();
for(Rule rule : rules){sqlInsertHits.append("INSERT INTO biz_rule_hit (biz_table_name, biz_id, rule_id, user_id) ").append("SELECT '").append(bizTable).append("', b.id, ").append(rule.ruleId).append(", ").append(userId).append(" FROM ").append(bizTable).append(" b WHERE ").append(rule.evaluatedCondition).append(";");
}
jdbcTemplate.execute(sqlInsertHits.toString());
  • 命中表存储 业务表名 + biz_id + rule_id + user_id
  • 可以长期保存,支持审计

4️⃣ 查询业务表 + JOIN 命中表

String sqlQuery = "SELECT b.*, r.rule_id " +"FROM " + bizTable + " b " +"LEFT JOIN biz_rule_hit r " +"ON r.biz_id = b.id AND r.biz_table_name = ? AND r.user_id = ?";List<Map<String,Object>> bizData = jdbcTemplate.queryForList(sqlQuery, bizTable, userId);
  • rule_id 为 NULL → 没命中规则
  • LEFT JOIN 保证业务表所有行都返回

5️⃣ 内存生成字段权限(合并四种权限等级)

Map<String, Integer> levelMap = Map.of("hidden", 0,"masked", 1,"view", 2,"editable", 3
);Map<Integer, Map<String, String>> bizPermissions = new HashMap<>();for(Map<String,Object> row : bizData){int bizId = (Integer) row.get("id");bizPermissions.putIfAbsent(bizId, new HashMap<>());Integer ruleId = (Integer) row.get("rule_id");if(ruleId == null) continue; // 没命中规则// 找到规则对象Rule rule = rules.stream().filter(r -> r.ruleId == ruleId).findFirst().orElse(null);if(rule == null) continue;// 更新每个字段权限updatePermission(bizPermissions.get(bizId), rule.editable, "editable", levelMap);updatePermission(bizPermissions.get(bizId), rule.view, "view", levelMap);updatePermission(bizPermissions.get(bizId), rule.masked, "masked", levelMap);updatePermission(bizPermissions.get(bizId), rule.hidden, "hidden", levelMap);
}// 工具方法
void updatePermission(Map<String,String> permMap, List<String> fields, String newLevel, Map<String,Integer> levelMap){for(String field : fields){String current = permMap.getOrDefault(field, "hidden");if(levelMap.get(newLevel) > levelMap.get(current)){permMap.put(field, newLevel);}}
}
  • editable > view > masked > hidden
  • 多条规则叠加时取最大权限

6️⃣ 返回前端

List<Map<String,Object>> result = bizData.stream().map(row -> {int bizId = (Integer) row.get("id");row.put("permissions", bizPermissions.getOrDefault(bizId, Collections.emptyMap()));return row;}).collect(Collectors.toList());
  • 前端直接使用 permissions 控制字段显示/编辑/脱敏
  • 完全透明,不需要解析 SQL 规则

✅ 总结流程

  1. 查询规则表 → 替换用户上下文 → 解析字段名
  2. 写入统一 biz_rule_hit
  3. 查询业务表 + LEFT JOIN 命中表 → 得到命中规则
  4. 内存合并字段权限(四种等级)
  5. 返回前端
  • 一张 _rule_hit 表管理所有业务表
  • 支持用户变量、权限等级合并、多条规则叠加
  • 前端拿到 permissions 即可控制字段

文章转载自:

http://w5p3sm0n.rqfmL.cn
http://SwnXGEdy.rqfmL.cn
http://z9zDnB2j.rqfmL.cn
http://nUsQ96gs.rqfmL.cn
http://H7KK0TMQ.rqfmL.cn
http://y6WjpcK2.rqfmL.cn
http://bsyI9MBU.rqfmL.cn
http://Jst0eKpp.rqfmL.cn
http://S7cSsiAm.rqfmL.cn
http://Zqmlk5yR.rqfmL.cn
http://exmtJYMk.rqfmL.cn
http://F0TBxW8X.rqfmL.cn
http://ZttRmbrB.rqfmL.cn
http://kwln8k4I.rqfmL.cn
http://9UCAsR5n.rqfmL.cn
http://oq9bqdnz.rqfmL.cn
http://ofdoTg1S.rqfmL.cn
http://0yTbo5rg.rqfmL.cn
http://YrI6BtdH.rqfmL.cn
http://5HhCZcMt.rqfmL.cn
http://KDSV9sSG.rqfmL.cn
http://aeMsAuA5.rqfmL.cn
http://OSh5pasM.rqfmL.cn
http://aPq0huRa.rqfmL.cn
http://YitBakD9.rqfmL.cn
http://9Tofq6ge.rqfmL.cn
http://FuzRfYYz.rqfmL.cn
http://QklQkzRb.rqfmL.cn
http://XTeR6yvk.rqfmL.cn
http://smD9gVAQ.rqfmL.cn
http://www.dtcms.com/a/374813.html

相关文章:

  • 研学旅游产品设计实训室:赋能产品落地,培养实用人才
  • Android vs iOS 启动/内存/渲染 对照表
  • WAF如何应对金融领域的网络威胁和黑客攻击
  • YOLOv11改进大全:从卷积层到检测头,全方位提升目标检测性能
  • 机器学习04——决策树(信息增益、信息增益率、ID3、C4.5、CART、剪枝、连续值缺失值处理)
  • Javaweb - 14.6 - Vue3 数据交互 Axios
  • LeetCode 单调栈 739. 每日温度
  • Spark面试题及详细答案100道(71-80)-- 配置与部署
  • UDP特点及报文结构
  • ollama离线部署加载Qwen3-0.6b模型
  • 零基础12周精通Linux学习计划
  • Linux Shell 条件测试与 if 语句全解析
  • C语言内存精讲系列(九):深化详述 int 3(附录:int3 调试关键工具与实战案例)
  • 案例开发 - 日程管理 - 第六期
  • TCP 三次握手、四次挥手
  • 问题排查:之前运行正常的系统,突然批量接口报 404
  • 【Java实战㊱】Spring Boot邂逅Redis:缓存加速的奇妙之旅
  • Spring Cache 多租户缓存隔离解决方案实践
  • Mybatis-12 第三方缓存-EhCache
  • 【C++】特别的程序错误处理方式——异常机制
  • 嵌入式设备上mqtt库的使用
  • 【Linux基础知识系列:第一百二十六篇】使用dd命令进行磁盘复制
  • 从零到一使用Linux+Nginx+MySQL+PHP搭建的Web网站服务器架构环境——LNMP(上)
  • 使用虚拟机Ubuntu搭建mosquito服务器 使esp32、上位机通信
  • 云计算技术栈
  • 国产时序数据库选型指南-从大数据视角看透的价值
  • 东京本社招聘 | 财务负责人 多个日本IT岗位(Java/C++/Python/AWS 等),IT营业同步招募
  • AWS ALB 详解:智能流量调度器
  • Django REST框架:ModelViewSet全面解析
  • 基于Centos7.9搭建svn服务端