
🧠 图解记忆: 权限必须进入检索条件,让模型从一开始就看不到无权访问的原文;事后过滤不够安全。
💡 答案要点
核心问题:
普通员工问AI:"高管的平均工资是多少?"
如果RAG没有权限控制 → AI可能从HR文档中检索到 → 信息泄露!四层权限隔离架构
┌─────────────────────────────────────────────┐
│ 权限隔离四层模型 │
├─────────────────────────────────────────────┤
│ Layer 1: 检索前过滤(Query时) │
│ → 用户问问题时,先判断他能访问哪些文档 │
├─────────────────────────────────────────────┤
│ Layer 2: Chunk级权限标签 │
│ → 每个Chunk有权限标签(机密/内部/公开) │
│ → 检索时只返回用户有权限的Chunk │
├─────────────────────────────────────────────┤
│ Layer 3: 生成时脱敏 │
│ → LLM回答时再次检查,避免泄露 │
├─────────────────────────────────────────────┤
│ Layer 4: 审计日志 │
│ → 记录所有检索和回答,用于事后审计 │
└─────────────────────────────────────────────┘Layer 1: Query时权限预过滤
python
class PermissionPreFilter:
def filter_query(self, user_query, user_role):
# 用户角色 → 可访问的文档范围
accessible_docs = self.role_to_docs.get(user_role, [])
# 在检索前限制搜索范围
return {
"query": user_query,
"allowed_doc_ids": accessible_docs # 只检索这些文档
}
# 示例
role_perms = {
"普通员工": ["公开文档", "产品手册"],
"经理": ["公开文档", "产品手册", "内部公告"],
"HR": ["公开文档", "HR文档"],
"高管": ["所有文档"]
}Layer 2: Chunk级权限标签
python
# 给每个Chunk打权限标签
chunk_permissions = [
{"chunk_id": "c1", "content": "公司产品介绍", "level": "public"},
{"chunk_id": "c2", "content": "销售数据报表", "level": "internal"},
{"chunk_id": "c3", "content": "员工工资表", "level": "hr_only"},
{"chunk_id": "c4", "content": "高管薪酬方案", "level": "executive_only"},
]
# 检索时过滤
def retrieve_with_permission(user_level, query):
chunks = vectorstore.similarity_search(query, k=10)
permission_rank = {
"public": 0,
"internal": 1,
"hr_only": 2,
"executive_only": 3
}
# 过滤:只保留用户有权访问的Chunk
accessible = [
c for c in chunks
if permission_rank[c.level] <= permission_rank.get(user_level, 0)
]
return accessibleLayer 3: LLM生成时脱敏
python
# 生成回答时加入权限检查指令
def generate_with_guardrails(context, user_query, user_level):
permission_instruction = {
"普通员工": "请只基于公开和内部信息回答,不要提及高管或HR专属信息",
"经理": "请只基于公开、内部和经理级信息回答",
"HR": "请只基于公开和HR文档回答",
"高管": "可以访问所有信息"
}
prompt = f"""
{permission_instruction[user_level]}
用户问题:{user_query}
参考信息:{context}
请谨慎回答。
"""
return llm.invoke(prompt)Layer 4: 审计日志
python
# 记录所有检索行为
def log_retrieval(user_id, query, retrieved_chunks, response):
audit_log = {
"timestamp": datetime.now(),
"user_id": user_id,
"query": query,
"retrieved_chunk_ids": [c.id for c in retrieved_chunks],
"chunk_levels": [c.level for c in retrieved_chunks],
"response_length": len(response),
"flagged": any(c.level == "restricted" for c in retrieved_chunks)
}
# 写入审计表(不可删除)
audit_table.insert(audit_log)
# 如果触发了权限边界,告警
if audit_log["flagged"]:
security_team.notify(audit_log)权限隔离vs普通RAG的架构对比
| 维度 | 普通RAG | 带权限隔离的RAG |
|---|---|---|
| 检索范围 | 全量向量数据库 | 按用户权限过滤 |
| Chunk标签 | 无 | 每个Chunk有权限级别 |
| LLM指令 | 通用Prompt | 加权限上下文 |
| 审计日志 | 无 | 完整记录 |
| 数据泄露风险 | 高 | 低 |
| 实现复杂度 | 低 | 高 |
面试话术
示例表达(仅在能用本人经历或可复现实验佐证时使用): "企业RAG权限隔离是2026年面试的高频考点。核心是四层防护:检索前过滤(用户能看到哪些文档)、Chunk级标签(每个片段有权限级别)、生成时脱敏(LLM回答时加权限指令)、审计日志(记录所有行为留痕)。实现难点是权限标签的建设——谁来定义、怎么维护、怎么和AD/LDAP集成。我做过一个案例是HR文档保护,普通员工问工资相关问题会被拦截,回答'抱歉您没有权限访问此信息'。"
📚 参考:Milvus:多租户与权限隔离实践
版本: v2.8 | 更新: 2026-04-06 | by 二狗子 🐕