☰
企业问数系统的数据权限与安全工程:从只读账号到查询审计
2026/10/14 21:21:48 网站建设 项目流程

本文是「企业问数系统落地」系列第十二篇。前面十一篇讲的是答得对不对、快不快、贵不贵,这篇讲一个在选型阶段最容易被一句话带过、上线后最容易被审计问住的问题:这套系统到底能碰到多少数据、以什么身份碰、碰完留下什么痕迹。

一、先纠正一个认知:安全不等于"内网部署"

在项目里我听过最多的一句安全结论是:

"我们内网部署,数据不出网,安全没问题。"

这句话对了一半。内网部署解决的是传输安全与网络边界,它让数据不离开你的机房。但它完全解决不了另一类风险——边界内的越权访问。

举个具体的例子。系统在内网、账号只读、网络隔离做得很好,然后一位业务人员在对话框里输入:

把公司所有人的工资明细列出来

请求完全合法:内网地址、只读账号、没有攻击特征。但如果系统真的答了,这就是一次严重的数据泄露——而且是从一个"设计上安全"的系统里流出来的。

所以结论很明确:安全必须分层做。内网部署只是其中一层,任何单点措施都会漏。下面给出一个可落地的五层模型,再逐层拆。


二、五层安全模型总览

层次解决什么问题主要手段
接入层用什么身份连数据库、能连到什么专用只读账号、最小权限授权、凭证管理与轮换
语义层能问什么对象、问到什么颗粒度对象可见性、行级过滤注入、指标白名单
执行层生成的查询会不会越界或跑飞SQL 白名单校验、只允许 SELECT、强制行数上限、超时熔断
输出层结果给谁看、能带出什么字段脱敏、导出管控、缓存按身份隔离
审计层出了事能不能追溯、排障有没有抓手查询记录、提问人、执行过程、返回规模

这张表有一个容易被忽略的设计取向:权限收口应该尽量往"语义层"放,而不是只放在数据库层。

原因在于两者面对的抽象层级不同:

  • 数据库层能表达的是"能不能读t_contract这张表";
  • 语义层能表达的是"这个角色能问'合同'这个业务对象,且只能问到本园区的合同"。

前者是技术权限,后者才是业务权限。只有技术权限的系统,最终往往被迫给一个大账号——因为业务角色和表权限根本不是一一对应的。

下面逐层展开。


三、接入层:最小权限不是"只读"两个字

很多项目对"最小权限"的理解止步于"给一个只有 SELECT 权限的账号"。这远远不够。一个可交付的最小权限设计至少要覆盖六个维度:

① 账号隔离。一个项目一个账号,不复用、不共享。共享账号的直接后果是:审计日志里只有"某账号查了敏感数据",追不到具体的人。

② 授权粒度:优先视图,而非基表。把需要查询的数据封装成视图再授权,好处是:

  • 视图里可以预先剔除敏感列、预先做行过滤;
  • 基表结构变化时,改视图不影响上层;
  • 授权清单一眼看得懂(业务视图名,而不是几十张表名)。

③ 列级控制。敏感列(身份证、手机号、薪资类字段)默认不授权。需要时也优先授掩码后的视图列,而不是原始列。

④ 严格只读。不仅要禁 INSERT / UPDATE / DELETE,还要考虑:

  • 禁用 DDL;
  • 禁用可写型临时表操作(如某些引擎的CREATE TABLE AS);
  • 关闭可能产生副作用的内置函数。

⑤ 网络与来源限制。账号只允许从平台服务所在网段连接,而不是"任意内网地址都可连"。

⑥ 凭证管理。凭证不进代码仓库、不进配置文件明文,走配置中心或密钥管理,并支持轮换。这一点在私有化项目里经常被忽视——最后变成某份 Excel 里存着一串密码。

示意性的授权语句(仅示意,各数据库语法差异较大,请以实际环境为准):

-- 示意:创建只读账号(示意语法) CREATE USER qa_reader WITH PASSWORD '******'; -- 示意:只授予业务视图的查询权限,而非基表 GRANT USAGE ON SCHEMA biz_view TO qa_reader; GRANT SELECT ON biz_view.v_contract TO qa_reader; GRANT SELECT ON biz_view.v_room_status TO qa_reader; GRANT SELECT ON biz_view.v_bill_receivable TO qa_reader; -- 示意:显式回收默认权限(不同引擎策略不同) REVOKE CREATE ON SCHEMA public FROM PUBLIC;

连接管理的正确姿势:先把"能连、能查到什么"验证清楚,再谈使用。连接配置集中维护,新系统接入时先做试查,确认权限边界与预期一致。


四、语义层:把权限收口到"业务对象"

这是我个人认为最值得投入的一层,因为它是技术权限和业务权限之间的翻译器。

语义层要管三件事:

4.1 对象可见性

角色能看见哪些业务对象。关键机制是"不暴露就不存在":

  • 薪资对象没有登记到语义层,那么"所有人的工资"这个问题在解析阶段就找不到对应对象,系统直接回"没有相关数据",而不是试图去猜某个表;
  • 这比在数据库层拦截更早、更干净,也更可解释。

4.2 行级过滤注入

数据权限("只能看本部门的""只能看本园区的")在查询生成阶段自动注入过滤条件,而不是依赖用户自觉加条件,也不依赖数据库的行级安全策略(很多客户环境并不支持或不愿启用)。

一个示意性的配置(示意,非真实格式):

# 示意:业务对象与行级权限 object: contract columns: - room_id - tenant_name - amount row_filter: by_role: park_manager: "park_code IN (:user_park_scope)" # 只看本园区 dept_viewer: "dept_code IN (:user_dept_scope)" # 只看本部门 group_admin: "1=1" # 集团口径,不过滤 sensitivity: normal

这样做有三个好处:

  1. 权限随对象走,新加一个助手时不用重新设计权限;
  2. 过滤条件是自动附加的,不依赖提问者是否"记得加条件";
  3. 可审计——每次查询实际附加了什么过滤条件,日志里看得见。

4.3 指标白名单

哪些指标可以问、按什么口径算,在语义层登记。没登记的指标,宁可答"暂不支持",也不要让模型现场推理一个算法出来。在安全语境下,"答不出"永远优于"猜一个"。

语义层说的"权限"和数据库说的"权限"不是一回事:前者决定业务上能问什么、问到多细,后者只决定技术上能读哪张表。


五、执行层:拦住"越权提问"和"查询跑飞"

先建立一个认知:在问数场景里,安全威胁的主要形态不是传统的 SQL 注入,而是"越权提问"。

原因是链路变了——SQL 不是用户写的,是模型生成的。用户手里没有输入框去注入,但他可以做两件事:

  1. 用自然语言诱导模型生成一个范围过大的查询("把所有历史数据都列出来");
  2. 通过多轮对话逐步试探(先问 A 表有哪些列,再问某列的全部取值)。

所以执行层的防护重点在生成的查询下发之前。建议设五道闸:

闸做什么拦什么
① 语法白名单只允许单条 SELECT,禁多语句、禁注释绕过、禁 DDL/DML 关键词拼接攻击、语句堆叠
② 对象校验查询中出现的表和列必须全部在授权清单内,逐个比对探测未授权对象
③ 强制行数上限自动追加 LIMIT,超限直接截断并提示全表拉取、批量外带
④ 超时与资源熔断执行超时、扫描行数/数据量超阈值即中断慢查询拖垮生产库
⑤ 并发配额与队列按角色限并发,超出排队(与性能篇同源)突发流量、个别用户刷查询

第 ② 道闸是最关键的一道,也是最容易被省掉的一道。它的实现不复杂:拿到查询语句后做一次解析,提取全部表名与列名,与"本次身份 + 本次意图对应的授权对象集合"做差集,非空即拒绝。

这里有一个工程细节值得强调:授权集合应该由"语义层对象"推导出来,而不是维护一份独立的表清单。否则每加一个业务对象就要同时改两处,迟早不同步。

回答规则(Prompt 模板)是"约束生成"的地方:约定选数据、写查询、解释结果的要求。它是执行层校验的前置防线——先约束生成得规矩,再做下发前校验。


六、输出层:结果本身也是数据

前面四层都在管"怎么查",这一层管"查出来的东西怎么出去"。三个容易被忽略的点:

6.1 缓存必须按身份隔离

这是实际项目里踩过坑的地方。问数系统通常会有结果缓存或语义缓存(相同/相似问题复用上一次的查询与结果),用来省延迟和成本。但如果缓存键只包含"问题文本 + 数据版本",不考虑身份与权限上下文,就会发生:

A 用户(集团管理员,可见全部园区)提问"各园区空置情况"→ 结果入缓存 B 用户(某园区管理员,只能看本园区)问同一句话 → 命中缓存 → 看到全部园区数据

这是一次不经过任何数据库层权限的越权泄露。修法很简单:缓存键必须包含权限上下文标识(角色 + 数据范围 + 敏感级别),或者更保守地——只对"授权集合完全相同"的身份共享缓存。

6.2 敏感字段掩码与实时判断

手机号、证件号一类字段,最好在输出层统一掩码,而不是在每一处查询里各写一遍。输出层掩码的好处是策略集中、便于调整,且能覆盖"通过明细导出的方式绕过去"的路径。

6.3 明细导出要管控

明细导出是最容易被忽视的外带通道。建议:行数上限 + 超限审批 + 导出行为留痕。特别注意区分"页面上看"和"导出成文件"两种权限——很多系统对前者做了控制,对后者没有。

三层答案(结论 → 图表 → 明细与来源)在安全语境下还有一个额外价值:每一次回答都自带出处。当有人质疑某个数字时,核对路径是现成的,不必再向数据团队申请一次取数——这本身也减少了"临时申请查看敏感数据"的场景。


七、审计层:别把它当合规摆设

很多项目把查询日志理解为"等保要求的合规动作"。实际上它是三类工作的共同基础设施:

用途一:安全审计。谁在什么时候问了什么、系统实际执行了什么查询、返回了多少行。当发生"某个敏感数被谁看过"的追问时,只有这个能回答。

用途二:故障排查。这是日常最高频的用途。用户反馈"这个数不对",需要能顺着记录看到:解析成了什么对象、召回了哪些样例、生成了什么查询、数据来源是哪几张表、执行耗时多少。没有过程记录的排查,只能靠猜。

用途三:运营优化。哪些问题被问得最多、哪些问题反复答不上来、哪些对象长期没人问——这些决定了下一步该补样例、补口径还是补培训。

一个可参考的记录字段清单:

时间戳 / 提问人 & 角色 / 原始问题 / 解析出的业务对象与指标 命中的样例(若有)/ 生成的查询(含注入的行级过滤条件) 数据来源对象 / 执行耗时 / 返回行数 / 是否截断 / 最终状态

注意最后几项:"是否截断"和"最终状态"必须记。一个被 LIMIT 截断却回给用户"完整结果"的系统,比答错更危险。


八、部署边界:私有化解决了一半问题

私有化/内网部署解决的是数据不出网。但如果方案里包含外部模型 API 调用,就要多问几句:

  • 送出去的是什么?最理想是只送"结构性信息"(字段名、类型、脱敏样例),不送真实业务数据值;
  • 送出去的结构信息本身敏感吗?表名和字段名经常携带业务信息(比如salary_detail、layoff_list),这本身就是泄露;
  • 能不能换成项目内模型?这是"模型可选择"这个设计取向的实际价值——模型是可替换部件,不是被绑定的黑盒,这决定了长期的合规弹性。

最后一句提醒:安全设计要写进项目配置与运行管理,而不是只写在方案文档里。方案里写"采用只读账号",和项目里真的有一个权限收紧过的账号、有凭证轮换机制、有可控的授权清单——是两回事。


九、五个常见反模式

反模式为什么危险换一种做法
全项目共用一个"超级只读"账号审计日志无法定位到人,一次泄露影响全部数据域一项目一账号;必要时按角色拆分账号
直接把业务基表暴露给查询敏感列裸露;表结构变更影响上层;授权清单无法阅读用视图封装 + 列级控制
只做网络隔离,不做语义层权限内网内的越权提问无任何拦截手段语义层做对象可见性与行级过滤注入
缓存键不含权限上下文一次缓存命中就是一次越权泄露缓存键纳入角色与数据范围
查询日志只记成功/失败出问题无法定位;审计问不住记录解析结果、查询语句、来源对象、返回规模

十、落地检查清单

按上线顺序排列,每一条都应该是"验证过的",而不是"设计过的":

  1. 只读账号已创建,且实测确认无法执行任何写操作;
  2. 授权对象为视图(或同等封装),授权清单可被人读懂;
  3. 敏感列已确认未授权,或已通过掩码视图暴露;
  4. 账号来源限制在平台服务网段内,实测其他网段连不上;
  5. 凭证不在代码/配置文件明文,具备轮换路径;
  6. 语义层已完成对象可见性登记——未登记对象提问时明确返回不支持;
  7. 行级过滤已在语义层配置,且验证过不同角色看到不同范围;
  8. 执行层五道闸全部开启,并实测"越权提问被拒"的用例;
  9. 缓存键已包含权限上下文,且用双角色用例验证过不串数据;
  10. 输出层掩码与导出管控生效,页面可看 ≠ 可导出;
  11. 查询记录字段完整(含"是否截断"与最终状态);
  12. 至少准备 5 个"越权提问"测试用例,纳入每次配置更新后的回归验证。

第 12 条值得单独说:安全用例和业务用例一样,必须进回归集。否则一次"顺手放宽权限",可能悄无声息地推翻前面十一条。


小结

回到开头那个问题:"内网部署就安全了吗?"

答案是:内网部署解决边界,只读账号解决身份,语义层解决业务权限,执行层解决查询范围,输出层解决数据外带,审计层解决可追溯。六件事分别对应六类风险,缺哪一块,风险就从哪一块进来。

如果只能记住一句话,我希望是这句:

安全不是给系统加一个开关,而是让每一个问题在被回答之前,先经过一次"这个身份该不该看到这个数据"的判断。

而这个判断,最好发生在业务对象这一层——因为它既是业务语言,又能被机器执行。


系列文章

篇主题
01技术架构解析
02智慧园区落地复盘
03口径治理实践
04选型评估指南
05问答样例库设计
06语义层建模
07接入层实践
08提示词工程化
09多轮追问与上下文
10评测与度量
11性能与成本
12数据权限与安全工程(本文)

说明:文中架构、配置与代码均为示意,用于表达设计思路,不代表产品实际实现细节;截图中的业务数据均为演示环境数据;安全策略需结合客户实际环境与合规要求确认后落地。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询