跳到主内容

MCP 服务器凭据怎么管:令牌不进上下文、最小权限与轮转机制

100%
MCP 服务器凭据怎么管:令牌不进上下文、最小权限与轮转机制

MCP 服务器的凭据风险不在传输层,而在「谁拿着令牌、令牌被谁看见」。按 Model Context Protocol 官方安全实践,有五条不能打折的硬规则:禁止令牌透传、必须校验受众、凭据不进模型上下文、按工具分域最小授权、以及可审计的轮转与清理。做到这五条,绝大多数 MCP 凭据事故就不会发生。

最危险的反模式:令牌透传

「令牌透传」指 MCP 服务器接受客户端送来的令牌,不校验它是不是发给自己的,就原样转发给下游 API 。官方规范明确禁止这种做法,因为它同时带来四类破坏:

  • 绕过安全控制:下游 API 的限流、请求校验往往依赖令牌受众,透传会让这些控制形同虚设。
  • 审计链断裂:下游日志里看到的是别人的身份,出事后无法定位到底是哪个客户端发起的。
  • 信任边界被打破:一个服务被攻破,攻击者可以拿同一个令牌访问其他所有接受它的服务。
  • 混淆副手问题:下游误以为令牌已被 MCP 服务器校验过,从而放松自己的检查。
一句话原则:MCP 服务器绝不接受任何不是明确颁发给自己的令牌。客户端给的令牌只是「用户是谁」的证明,访问下游资源必须用服务器自己持有的、独立申请的凭据。

五条硬规则

规则具体要求违反后的后果
受众必须校验校验 aud / resource 声明是否指向本服务器,拒绝通用受众跨服务令牌复用,权限被放大
禁止透传访问下游用服务器自己的令牌,不转发客户端令牌混淆副手、审计失效
绝不记录凭据不写 Authorization 头、令牌、 code 、密钥;结构化日志脱敏日志成为凭据泄露最大出口
最小权限分域不使用兜底 scope,按工具或能力拆分并逐个校验一次泄露等于全量失守
凭据独立存放存密钥管理服务或加密存储,不进源码仓库,配置缓存有淘汰策略密钥随代码外流、长期不失效

凭据到底该放在哪

把凭据分层,是避免它流进模型上下文的前提。推荐的三层结构是:

  • 服务器自身的服务端密钥:放在密钥管理服务或环境变量里,由服务器启动时读取,永不作为参数传给工具、永不出现在工具返回值里。
  • 按用户维度的第三方令牌:用户授权后拿到的下游令牌,缓存在服务端加密存储中,键名绑定用户标识,并配置明确的过期与淘汰策略,避免复用已失效令牌。
  • 会话层标识:MCP 的会话标识只用于路由与恢复连接,不能当作身份凭证使用。

最容易出问题的是第二层:为了省事把用户令牌塞进上下文或工具参数,模型一旦被提示注入诱导,就会把令牌当作普通文本输出。正确做法是令牌只在服务端内部流转,工具对模型暴露的永远是「已授权」这类布尔状态或一个不透明的资源句柄。

缓存与轮转的最小实现

# 缓存键绑定用户标识,避免越权命中
cache_key = f"token:{user_id}:{downstream_name}"

def get_downstream_token(user_id, downstream):
    tok = cache.get(cache_key)
    if tok and not is_expired(tok):
        return tok            # 命中且未过期
    tok = refresh_with_refresh_token(user_id, downstream)
    cache.set(cache_key, tok, ttl=tok.expires_in * 0.8)  # 提前过期,留出刷新窗口
    return tok

# 日志脱敏:只写标识,不写值
log.info("downstream token refreshed", extra={"user": user_id, "downstream": downstream})

日志与会话的两条红线

  • 日志只能有标识不能有值:Authorization 头、令牌、授权码、密钥一律不落日志;结构化日志中的敏感字段统一脱敏,排查需要时用关联 ID 到内部系统查详情。
  • 会话标识不可信:把它当成普通不可信输入处理,不要基于它做授权判断,认证状态变化时重新生成,并在服务端校验其生命周期。使用安全的非确定性随机会话标识,避免可猜测的顺序 ID;存储或传输与会话相关的数据时,把用户标识与会话标识组合成键,这样即便会话标识被猜到也无法冒充他人。

上线前检查清单

  1. 确认所有入站令牌都做了受众校验,非本服务器的令牌一律拒绝,且没有任何路径把客户端令牌转发给下游。
  2. 确认服务端密钥来自密钥管理服务或环境变量,代码仓库、镜像层、构建产物里都搜不到明文密钥。
  3. 检查日志配置:Authorization 头、令牌、授权码、密钥均不落盘,结构化日志字段已脱敏。
  4. 确认授权 scope 按工具或能力拆分,不存在一个兜底 scope 覆盖全部能力,且每次调用都校验所需 scope 。
  5. 确认用户令牌缓存有过期与淘汰策略,认证状态变化后缓存失效,会话标识为随机生成且不与授权绑定。

相关阅读:MCP 远程服务器的 OAuth 授权:从零到可用、MCP 安全风险全景:提示注入、权限边界与 URL 校验、MCP 配置放哪一层:local 、 project 、 user 三种作用域。


本地 stdio 模式的 MCP 服务器也要这么严格吗
要。本地服务器运行在用户机器上,反而更危险:它能访问用户文件系统与本地进程,一旦凭据处理不当,泄露面比远程更大。差别只在传输与部署,不在凭据规则。

工具参数里能不能直接传 API Key
不能。工具参数会进入模型上下文,也可能被原样写进对话记录与日志。正确做法是由服务器在内部读取凭据后发起请求,工具只暴露必要的业务参数。

令牌缓存多久合适
不要用到期时间本身,建议按有效期的 70% 到 80% 设置缓存过期,留出刷新窗口。同时必须有主动淘汰:用户解绑、权限变更、服务端检测到异常时立即清除。

延伸阅读:MCP 服务器连数据库的只读约束与安全边界
这篇有帮助吗?
云上的幻象
云上的幻象查看主页

七彩云博客,分享 WordPress 建站实战与 AI 工具测评,覆盖服务器运维、站长工具、软件资源与电商运营干货,专注原创实用的主题插件、网站加速与安全优化教程。

968文章4评论

相关文章

评论 (0)

欢迎你,新朋友,感谢参与互动!文明发言,理性交流 · 首次评论将在审核后展示