用授权服务器保护 MCP 服务器

HN Shipped with Claude 2026-08-13T01:14:48.346311

MCP(Model Context Protocol,模型上下文协议)正迅速成为大型语言模型(LLM)与业务逻辑交互的标准 API。和 REST 诞生初期一样,开发者们跑得很快,经常为了功能而牺牲安全。

我们已经在这些新技术上看到了十多年前犯下的那些安全错误。

MCP 安全公告列表里就有不少例子,列出了路径遍历、路径校验和注入等漏洞。从租户隔离失效、网络配置错误,到工具投毒,这些负面影响都应当避免。由于智能体(agent)是自主行动的,一个配置错误的 MCP 服务器,其破坏力比一个 REST 端点大得多。

最简单的缓解办法是什么?使用授权服务器(Authorization Server,AS)来强制要求身份验证和授权。如果你的 MCP 服务器涉及任何机密内容,或者它提供的数据和功能会随请求用户不同而变化,那就把它牢牢锁住。公开文档或共享资源(比如我们的 FusionAuth 文档 MCP 服务器)不需要身份验证,但除此之外的任何东西,都需要一层真正的安全防护。

实际上需要两层防护:一层放在 MCP 服务器前端,这是本文将重点讨论的;另一层放在后端,标准只是顺带提及,并没有详细规定。

MCP 规范并没有在协议层面强制安全要求,所以「交由实现者处理」往往就变成了「先拖着,直到出了入侵事件才重新考虑」。别让这种事发生在你身上。

幸运的是,MCP 确实定义了一种用 OAuth 保护远程服务器的方法。看来我们还是从 REST 时代的错误中学到了一点东西。

这种方案把认证工作交给 AS 完成:在请求到达你的服务器之前,AS 会先确认用户的身份和权限。具体通过 OAuth 授权码模式(Authorization Code)实现,用到作用域(scopes)和授权同意(consents)这些大家熟悉的概念。虽然 MCP 有一个扩展支持客户端凭证(client credentials)访问,但本文重点讨论更常见的「代表用户」(on-behalf-of)流程:由用户明确授权 MCP 客户端代表自己访问 MCP 服务器。

下面就是让 MCP 客户端完成认证与授权、进而使用你受保护的远程 MCP 服务器的完整流程:

  1. MCP 服务器发现
  2. MCP 客户端注册
  3. 用户认证
  4. 用户授权
  5. 访问令牌签发
  6. 访问令牌校验
  7. 使用 MCP

我们逐项来说。

MCP 服务器发现

首先,需要把 MCP 服务器的地址配置到 MCP 客户端(比如 Claude Desktop 或 AI Agent)里。具体怎么配置取决于客户端,可能是编辑一个 JSON 文件,也可能是在表单里填一个 URL。

当客户端第一次访问 MCP 服务器时,服务器会回应:"我不认识你,请到这里来为我获取凭证。"这条重定向流程的技术细节由 RFC 9728 定义。

这个响应会把客户端导向一个 MCP 服务器信任的授权服务器(AS)。

客户端注册

MCP 客户端到达 AS 之后,AS 需要先了解它的一些情况。完成这一步有几种方式,按规范中的评估顺序排列:

  1. 提前在 AS 上注册 MCP 客户端。也就是说,由某个其他流程预先在客户端与 AS 之间建立了关联。这种方式被称为"带外"(out of band),听起来很神秘,实际意思是"我们不在乎它是怎么发生的,只要发生了就行"。这就好比出席一场正式晚宴,走到门口亮一下邀请函——你已经被邀请了,在跟门口的人开口之前,对方就知道你是谁。

  2. 在 MCP 客户端第一次与 AS 交互时完成注册。这里有两条技术路径:客户端 ID 元数据文档(Client ID Metadata Documents,CIMD)和动态客户端注册(Dynamic Client Registration,DCR)。前者更新一些,看起来是未来的方向;后者则被明确保留下来,用于向后兼容。这就像酒吧门口的保安查验驾照——只要满足一定条件,就能进去。

  3. 直接让用户提供凭证。这种方式我还没在实际环境中见过,它把协调工作完全推给了人。好比你没带邀请函就去参加聚会,主人得亲自走到门口替你作保。

选择哪种客户端注册方式,会直接影响你在安全性和便利性之间的取舍。

用户认证

AS 识别出 MCP 客户端之后,用户还需要登录。

认证过程可以采用 AS 认可的任何形式:密码、通行密钥(passkey)、第三方单点登录(SSO)、多因素认证(MFA)都可以。MCP 客户端并不关心具体用了哪种。

通常,AS 会向用户展示一个授权确认页面,列出 MCP 客户端所需的 OAuth scope(授权范围)。具体映射关系取决于你的实现,但通常一个 scope 对应一组 MCP 客户端可以访问的工具。

比如,account:read 这个 scope 可以映射到下面这些虚构的端点和方法:

相比之下,account:write 这个 scope 则可能授予

权限范围(scope)分为必选和可选两种。不管哪种情况,只要用户觉得 MCP 客户端申请的权限太宽泛,都应该有权取消授权。

访问令牌的签发

用户在授权服务器(AS)上完成身份验证并同意授权后,AS 会向客户端签发一个有时效的 OAuth 访问令牌(Access Token)。MCP 客户端保存这个令牌,并在访问受保护的 MCP 服务器时把它出示给对方。

相比其他智能体工具,MCP 在安全上的一个好处是:令牌由 MCP 客户端持有,不会交给大语言模型(LLM)。请求发出时,MCP 客户端会自动把令牌附加进去,整个过程对上层透明。

这样一来,攻击者想通过诱导 LLM 直接套出凭据就行不通了。

访问令牌的校验

MCP 服务器收到令牌后,会从受众(audience)、过期时间、签发方(issuer)和允许的权限范围等方面进行校验。

例如,如果 AS 签发的访问令牌是 JWT(JSON Web Token),MCP 服务器还应该遵循 JWT 的最佳实践,比如验证签名。

访问 MCP 功能

令牌校验通过后,MCP 服务器会基于已验证的身份,继续执行所请求的调用。MCP 客户端响应用户原始请求所需的数据和功能,这时才真正可用。

正如前面所说,MCP 服务器背后的身份认证与授权层非常重要,但本文不打算展开,原因有三:

规范对更深层的环节只给了一条建议:不要把交给 MCP 服务器的访问令牌继续传给下游服务。但正确落实这个授权模型,对数据安全至关重要。

在把任何东西作为 MCP 服务器开放之前,先想清楚:哪些用户应该能访问哪些服务、数据和功能。

接下来是什么?

MCP 发展得很快,REST 时代犯过的安全错误已经在现实场景里重新出现。好在 MCP 规范并没有让你从零开始设计一套安全模型,而是直接站在 OAuth 这个久经考验的标准之上——它经过了多年的专家审查,背后还有成熟的生态系统支撑。

把身份认证和授权交给授权服务器(AS),你就能获得经过验证的身份、用户可控的授权同意,以及有时效性的访问令牌。

在构建 MCP 服务器时,有几条原则值得记在心里:

工具和基础设施已经就绪。请在你的 MCP 服务器出问题之前把它保护好,而不要等到事后才补救。

查看原文