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

登录之后还不够:企业 RAG 知识库怎么防止用户越权访问?

通过登录,系统可以知道当前请求来自哪个用户;通过 Gateway,系统可以统一校验 Token,并把用户身份透传给下游服务。

但是,仅仅知道“这个人是谁”还不够。

企业知识库真正关心的是另一个问题:

这个用户能不能访问这个资源?

比如:

  • A 用户能不能查看 B 用户创建的知识库?
  • 普通用户能不能查看所有用户的问答日志?
  • 用户上传文档时,能不能往别人的知识库里上传?
  • 用户提问时,检索范围是不是只在自己的知识库内?
  • 管理员为什么可以查看全局任务?

这些问题都属于资源隔离和权限边界。

这一篇要讲清楚 KnowHub 如何在登录认证之后继续做用户资源隔离,以及基础后台管理端如何建立在 USER / ADMIN 角色之上。


01 登录认证不等于资源授权

很多初学者会把“登录”和“有权限”混在一起。

其实它们不是一回事。

登录认证解决的是:

你是谁?

资源授权解决的是:

你能访问什么?

用户成功登录,只能说明他是系统里的合法用户。它并不意味着这个用户可以访问所有知识库、所有文档和所有日志。

举个例子。

A 用户登录后,Token 中的身份是:

userId = 1 role = USER

B 用户创建了一个知识库:

kbId = 100 userId = 2

A 用户如果请求:

GET /kb/100

Gateway 只能判断 A 用户已经登录,它并不知道 kbId=100 属于谁。

真正的判断必须在 knowledge-service 中完成:

查询 knowledge_base.id = 100 判断 knowledge_base.user_id 是否等于当前 userId 如果不相等,则拒绝访问

这就是为什么企业系统不能只做登录,还必须在业务层做资源归属校验。


02 用户资源隔离的 4 个基本原则

KnowHub 的资源隔离遵循几个原则。

不相信前端传入的 userId

前端传来的参数都可以被用户修改。

所以用户侧接口不应该依赖前端传入的 userId,而应该使用 Gateway 透传后由下游服务构造出的当前用户身份。

也就是:

当前用户 = UserContext.getUserId()

而不是:

当前用户 = request.getParameter(”userId”)

所有用户侧查询都带当前 userId

查询“我的知识库”时,SQL 条件中必须包含当前用户 ID。

逻辑类似:

select * from knowledge_base where user_id = 当前用户ID and status = ENABLED

这样 A 用户只能看到自己的知识库。

跨用户访问不要泄露资源信息

如果 A 用户访问 B 用户的知识库,系统可以返回无权限,也可以返回资源不存在。

很多系统会选择返回“资源不存在”,这样可以减少资源探测风险。

A 用户访问 /kb/100 但 kbId=100 属于 B 用户 系统返回:知识库不存在

从用户体验看,这和真的没有这个知识库类似;从安全角度看,攻击者无法判断这个 ID 是否真实存在。

写操作更要先校验归属

不仅查询要校验,写操作更要校验。

比如:

  • 上传文档前,先校验知识库是否属于当前用户。
  • 删除知识库前,先校验知识库 owner。
  • 发起问答前,先校验知识库 owner。
  • 重建索引前,先校验文档是否属于当前知识库和当前用户。

只有这样,用户才不能把数据写进别人的资源里。


03 知识库 owner 校验怎么做

知识库是 KnowHub 中最核心的资源边界。

在 knowledge_base 表中,每条记录都应该有一个 user_id 字段。

它表示这个知识库属于哪个用户。

简化结构如下:

id user_id name description status created_at updated_at

当用户访问某个知识库时,knowledge-service 要做两件事:

1. 查询知识库是否存在 2. 判断 knowledge_base.user_id 是否等于当前用户 ID

如果不相等,就不能继续访问。

创建知识库

创建知识库时,前端只需要提交名称和描述。

用户 ID 不应该由前端传入,而应该来自当前登录用户。

流程如下:

前端提交 name、description -> Gateway 校验 Token -> knowledge-service 获取当前 userId -> 创建 knowledge_base -> knowledge_base.user_id = 当前 userId

这样用户无法伪造 owner。

查询我的知识库

查询列表时,只返回当前用户自己的数据:

where user_id = 当前 userId

管理员查看全局知识库则走 /admin/** 管理端接口,不和普通用户接口混用。

查看知识库详情

查看详情时,除了按 ID 查询,还要检查 owner。

错误思路:

select * from knowledge_base where id = kbId

正确思路:

select * from knowledge_base where id = kbId and user_id = 当前用户ID

重点是不能遗漏 owner 条件。

knowledge_base 表设计

user_id 是资源隔离的核心字段,必须出现在索引中。

CREATE TABLE knowledge_base ( id BIGINT NOT NULL AUTO_INCREMENT COMMENT '知识库ID', user_id BIGINT NOT NULL COMMENT '知识库owner用户ID', name VARCHAR(100) NOT NULL COMMENT '知识库名称', description VARCHAR(500) DEFAULT NULL COMMENT '知识库描述', status VARCHAR(32) NOT NULL DEFAULT 'ENABLED' COMMENT '状态:ENABLED/DISABLED/DELETED', created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (id), KEY idx_kb_user_status_updated (user_id, status, updated_at), KEY idx_kb_user_name (user_id, name) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='知识库表';

idx_kb_user_status_updated 用于“查询我的知识库”这类高频接口;idx_kb_user_name 可以辅助同一用户下的名称查询或名称查重。


04 Redis owner 缓存设计

知识库 owner 校验会被频繁使用。

比如:

  • 查询知识库详情。
  • 上传文档。
  • 查询文档列表。
  • 发起向量检索。
  • 发起 RAG 问答。

如果每次都查 MySQL,压力虽然不一定很大,但链路会更长。KnowHub 使用 Redis 缓存知识库 owner,减少重复查询。

缓存 Key 设计

owner 缓存 key 可以设计为:

rag:kb:owner:{kbId}

例如:

rag:kb:owner:100

value 保存 owner 用户 ID:

2

查询流程

校验知识库 owner 时,流程如下:

1. 根据 kbId 读取 Redis:rag:kb:owner:{kbId} 2. 如果命中,拿到 ownerUserId 3. 判断 ownerUserId 是否等于当前 userId 4. 如果未命中,查询 MySQL 5. MySQL 查到后写入 Redis 6. 再进行 owner 判断

这样第一次访问会查数据库,后续访问可以直接命中 Redis。

缓存失效

缓存不是数据库,不能只写不删。

当知识库被删除、状态变化或 owner 发生变化时,需要删除对应缓存。

否则可能出现:

MySQL 中知识库已删除 Redis 中 owner 仍然存在 系统误以为资源还能访问

缓存不是安全边界

这里要强调一点:Redis 缓存只是加速 owner 判断,不是权限本身。

真正的权限依据仍然是数据库中的资源归属。

如果缓存未命中,就回源 MySQL。如果缓存异常,也应该能回退到数据库校验,而不是直接放行。


05 文档、索引任务和问答中的隔离

知识库 owner 校验不是只在知识库接口里用。

它贯穿文档、索引任务和问答链路。

文档上传

用户上传文档时,必须先校验:

当前用户是否拥有这个 kbId

只有校验通过,系统才会继续:

上传文件到 MinIO 写入 document_info 创建 index_task 发送 RabbitMQ 消息

如果不做这个校验,用户就可能往别人的知识库上传文档。

文档列表

查询文档列表时,也要先校验知识库归属。

用户只能查看自己知识库下的文档。

向量检索

向量检索时,不能只按问题相似度查 TopK。

必须加上范围过滤:

user_id = 当前用户ID kb_id = 当前知识库ID

否则可能出现严重问题:用户提问时,检索到了别人知识库里的片段。

这比普通接口越权更隐蔽,因为用户可能不会直接看到文档列表,却会在答案里看到不该看到的信息。

RAG 系统不能只相信相似度排序,必须先限制检索范围。

RAG 问答

问答链路也要先校验知识库归属。

流程大致是:

用户提问 -> 校验 kb owner -> 问题向量化 -> 按 userId 和 kbId 检索 -> 拼接 Prompt -> 调用模型 -> 写 qa_log -> 返回答案和引用来源

qa_log 中也应该记录 userId 和 kbId,方便后续管理端查询和问题排查。

索引任务

索引任务也要带上 userId、kbId、documentId。

这样管理员能看到全局任务,普通用户只能看到自己文档对应的任务。

RabbitMQ 消息中也应该包含这些 ID,便于 task-service 消费时校验和更新状态。


06 基础后台管理端

KnowHub 不只有用户端,还有基础后台管理端。

管理端的目标不是做一个复杂企业后台,而是提供运维视角,让管理员能看见系统运行情况。

USER 和 ADMIN

当前基础角色包括:

USER ADMIN

普通用户登录后只能访问用户端。

管理员登录后可以访问管理端。

角色信息会写入 JWT,Gateway 根据角色拦截 /admin/**。

管理端能做什么

基础管理端通常包含这些能力:

  • 查看用户列表。
  • 修改用户状态。
  • 修改用户角色。
  • 查看全部知识库。
  • 查看全部文档。
  • 查看索引任务。
  • 筛选失败任务。
  • 手动重试失败任务。
  • 查看问答日志。

这些功能对排查问题很重要。

比如用户说“我的文档一直不能问答”,管理员可以查看:

文档是否上传成功 索引任务是否 SUCCESS 失败原因是什么 RabbitMQ 消息是否消费 MinIO 文件是否存在 qa_log 中是否有模型失败记录

Gateway 管理员拦截

管理端接口必须走 /admin/**。

Gateway 看到这个路径后,会检查 Token 中的 role。

如果不是 ADMIN,直接拒绝。

这比只在前端隐藏菜单更可靠。

管理端前端不是安全边界

前端可以做角色判断,提高体验。

比如普通用户登录管理端时,前端提示:

当前账号不是管理员

但真正的安全边界在后端。

因为用户可以绕过前端,直接调用接口。所以 /admin/** 必须由 Gateway 和后端接口共同保护。


07 为什么当前不是完整 RBAC

KnowHub 当前使用的是基础角色模型。

也就是:

USER ADMIN

这已经能满足学习项目中的用户端和管理端隔离。

但它不是完整 RBAC。

完整 RBAC 通常还包括:

  • 用户表。
  • 角色表。
  • 权限表。
  • 用户角色关系表。
  • 角色权限关系表。
  • 菜单权限。
  • 按钮权限。
  • 数据权限。
  • 操作审计。

比如一个完整企业后台可能有这些角色:

超级管理员 知识库管理员 审计员 普通用户 只读用户

不同角色能访问不同菜单、不同接口、不同数据范围。

KnowHub 当前没有把 RBAC 做到这个复杂度,是有意取舍。

原因是本系列主线是 AI 知识库 / RAG 平台,不是权限系统教程。我们先用 USER / ADMIN 建立清晰边界,后续可以把完整 RBAC 作为企业化扩展。


08 常见问题排查

UserContext 为空

现象:访问知识库接口时提示未登录或用户上下文不存在。

排查顺序:

  1. 前端是否携带 Authorization。
  2. 请求是否经过 Gateway。
  3. Gateway 是否写入X-User-Id
  4. knowledge-service 是否配置 UserContextInterceptor。
  5. 请求头名称是否一致。

A 用户能看到 B 用户数据

这是严重问题。

排查顺序:

  1. 查询接口是否带了user_id条件。
  2. 详情接口是否校验 owner。
  3. 文档接口是否先校验 kb owner。
  4. 向量检索是否按 userId/kbId 过滤。
  5. 管理端接口是否误暴露给普通用户。

Redis owner 缓存脏数据

现象:数据库中知识库已经删除或变更,但接口仍然认为它存在。

排查:

  • 删除知识库时是否删除rag:kb:owner:{kbId}
  • 缓存 TTL 是否过长。
  • 是否有回源 MySQL 校验。
  • Redis 中的 value 是否和数据库一致。

普通用户访问管理接口

普通用户访问 /admin/** 返回 403 是正常的。

如果普通用户能访问成功,要检查:

  1. Token 中 role 是否错误。
  2. Gateway 是否启用了 admin 路径校验。
  3. 路径是否没有以/admin/开头。
  4. 后端管理接口是否绕过了 Gateway。

管理员登录后仍然无权限

排查顺序:

  1. 数据库中用户 role 是否为 ADMIN。
  2. 登录后新签发的 Token 是否包含 ADMIN。
  3. 前端是否仍使用旧 Token。
  4. Gateway 是否正确解析 role。
  5. role 大小写是否一致。

向量检索返回了疑似他人知识库的内容

这是 RAG 系统里很隐蔽也很严重的问题。

排查顺序:

  1. 向量检索 SQL 是否带了 userId 过滤条件。
  2. userId 是否从 UserContext 获取,而不是从请求参数获取。
  3. pgvector 向量记录是否包含 userId 字段。
  4. task-service 写入向量时是否正确设置 userId。
  5. 查询条件正确但仍异常时,再检查 pgvector 索引和查询执行计划。

09 动手验证:用户资源隔离是否生效

第一步,注册两个用户 A 和 B,分别登录获取各自的 Token。

POST http://localhost:8080/auth/register Body: {”username”:”userA”,”password”:”123456”,”nickname”:”用户A”}
POST http://localhost:8080/auth/login Body: {”username”:”userA”,”password”:”123456”} 预期结果:返回用户 A 的 Token

同样方式注册并登录用户 B。

第二步,用户 A 创建一个知识库,记下 kbId。

POST http://localhost:8080/kb Authorization: Bearer 用户A的Token Body: {”name”:”A的知识库”,”description”:”资源隔离验证”} 预期结果:创建成功,返回 kbId

第三步,用户 B 访问用户 A 的知识库。

GET http://localhost:8080/kb/{用户A的kbId} Authorization: Bearer 用户B的Token 预期结果:返回“知识库不存在”或类似错误

第四步,用户 B 往用户 A 的知识库上传文件。

POST http://localhost:8080/kb/{用户A的kbId}/documents/upload Authorization: Bearer 用户B的Token Body: form-data,file=任意 txt/pdf 文件 预期结果:返回错误,不能上传成功

第五步,用户 A 访问自己的知识库。

GET http://localhost:8080/kb/{用户A的kbId} Authorization: Bearer 用户A的Token 预期结果:正常返回知识库详情

第六步,普通用户 A 访问管理端索引任务。

GET http://localhost:8080/admin/index-tasks Authorization: Bearer 用户A的Token 预期结果:返回 403

如果某一步不符合预期,先确认 Gateway 是否正常透传了 X-User-Id,再确认当前登录用户的 userId 是否和知识库的 user_id 对应,然后逐步排查 Service 查询条件、Redis owner 缓存、MySQL 数据和 Gateway 管理员路径校验。


本章小结

这一章我们讲清楚了 KnowHub 的用户资源隔离和基础后台管理设计。

登录认证只能证明用户是谁,不能代表用户能访问所有资源。真正的资源边界必须在业务服务中校验。

知识库是 KnowHub 的核心资源,因此 knowledge_base.user_id 是用户隔离的基础。用户创建知识库时,owner 来自当前登录用户;用户查询、上传文档、发起问答时,都必须校验知识库归属。

为了减少高频 owner 校验带来的数据库访问,系统使用 Redis 缓存 rag:kb:owner:{kbId},但缓存只是加速手段,不能替代数据库中的权限依据。

管理端基于 USER / ADMIN 做基础角色隔离。Gateway 负责拦截 /admin/**,管理端接口负责提供用户、知识库、文档、索引任务和问答日志的运维视角。

下一章,我们将进入知识库管理与文档元数据,开始讲用户真正操作的第一个业务核心:创建知识库、上传文档,以及如何把文件记录成可追踪的数据。


作者有话说

如果这篇文章对你有帮助,欢迎点个关注。

这个专栏会持续更新KnowHub / RAG 平台实战内容,后面会继续把知识库管理、文档元数据、文件存储、文档解析和索引任务拆开讲清楚。

如果你想对照代码学习,可以结合下面两个仓库:

rag-demo-monolith:单体版源码

适合先理解 RAG 核心闭环,把业务链路跑通。

仓库地址:

https://gitee.com/MrLuoBin/rag-demo-monolith.git
https://github.com/luobinsnbb/rag-demo-monolith.git

克隆命令:

git clone https://gitee.com/MrLuoBin/rag-demo-monolith.git

rag-platform:微服务版源码

适合继续学习 Gateway、Auth、Knowledge、Task 的企业级拆分方式。

仓库地址:

https://gitee.com/MrLuoBin/rag-platform.git

克隆命令:

git clone https://gitee.com/MrLuoBin/rag-platform.git

如果你在做 AI 知识库或 RAG 项目,建议把“用户能访问什么资源”作为第一优先级设计。RAG 系统一旦发生检索越权,风险比普通接口越权更隐蔽。

学AI大模型的正确顺序,千万不要搞错了

🤔2026年AI风口已来!各行各业的AI渗透肉眼可见,超多公司要么转型做AI相关产品,要么高薪挖AI技术人才,机遇直接摆在眼前!

有往AI方向发展,或者本身有后端编程基础的朋友,直接冲AI大模型应用开发转岗超合适!

就算暂时不打算转岗,了解大模型、RAG、Prompt、Agent这些热门概念,能上手做简单项目,也绝对是求职加分王🔋

📝给大家整理了超全最新的AI大模型应用开发学习清单和资料,手把手帮你快速入门!👇👇

学习路线:

✅大模型基础认知—大模型核心原理、发展历程、主流模型(GPT、文心一言等)特点解析
✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑
✅开发基础能力—Python进阶、API接口调用、大模型开发框架(LangChain等)实操
✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用
✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代
✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经

以上6大模块,看似清晰好上手,实则每个部分都有扎实的核心内容需要吃透!

我把大模型的学习全流程已经整理📚好了!抓住AI时代风口,轻松解锁职业新可能,希望大家都能把握机遇,实现薪资/职业跃迁~

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

http://www.jsqmd.com/news/1341192/

相关文章:

  • PHP7 数组的实现
  • 如何快速配置PUBG-Logitech:3步实现智能游戏辅助工具的零文件修改压枪
  • 图解RAG,一张图理解检索增强生成
  • 推荐2026年广受好评的4款RFID资产管理系统 - 全域品牌推荐
  • 高温高速超大构件皆可测!DIC攻克多尺度全场应变
  • 青浦徐泾配镜亲测!国展旁这家眼镜店,配儿童防控镜真的靠谱 - 林州鸿途网络
  • 双栈兼容IP离线库:IPv6时代风控与运维的“无感升级”最优解
  • 实用Blender插件大全:一站式提升3D创作效率的终极指南
  • 中国学历证书公证怎么认证?涉外模板+认证全透明! - 指上通
  • 推荐几家国内靠谱的GEO服务商? - 产品评测官
  • 半年自研144个应用!郑州一建益企联 从数据孤岛到智能管控!!
  • Python基础-基础语法(五)
  • Siri AI升级:从平淡体验到智能助手的工程挑战与实用指南
  • 「APP软件开发」与微服务 / 云原生结合的工程实践
  • Horos医学影像软件:macOS上的免费专业级DICOM查看器终极指南
  • 助贷风控效率革命:昆仲AI如何通过征信报告解读、流水解析与法诉查询工具终结人工核查三大顽疾? - 甄选测评官
  • Thor 上手第一天 Checklist
  • 凌晨两点,OpenCode 优先级队列把我的上下文截断了:回灌策略如何吃掉 40% 的关键结果
  • 生成式引擎优化哪家好?不同预算和需求对应的服务商盘点 - 全域品牌推荐
  • 兴义房屋漏水怎么办?超人防水补漏深耕全城,专注解决兴义各类季节性渗漏难题2026.8月新 - 超人防水
  • 终极免费绘图神器:draw.io桌面版完全使用指南
  • 别只看最终答案:多模态 RAG 需要一套文档解析评测包
  • 5分钟快速上手FanControl中文版:Windows风扇控制终极指南
  • 如何在ComfyUI中实现专业级AI面部替换:ReActor换脸插件完全指南
  • 2026年充电桩加盟品牌怎么选?鸿嘉利新能源领跑全场景解决方案 - 全域品牌推荐
  • 暗黑破坏神2存档编辑器终极指南:d2s-editor完整使用教程 [特殊字符]
  • 宁夏优质月子餐培训中心推荐,深耕银川等地区,优厚家庭服务赋能技能提升稳就业 - 十大品牌榜
  • 程序员接私活验收演示指南:如何让演示结果100%可复现
  • AI Agent大师之路:从认知架构到自主智能体的完整设计哲学
  • 《迷你世界》UGC3.0角色模块标准化接口设计与实践