领先一步
VMware 提供培训和认证,助您加速进步。
了解更多Spring AI 支持模型上下文协议(简称 MCP),它允许 AI 模型以结构化的方式与外部工具和资源进行交互和访问。通过 Spring AI,开发者只需几行代码即可创建自己的 MCP 服务器并向 AI 模型公开功能。
MCP 服务器可以本地运行,使用 STDIO 传输。要将 MCP 服务器暴露给外部世界,它必须暴露一些标准的 HTTP 端点。虽然私下使用的 MCP 服务器可能不需要严格的身份验证,但企业部署需要强大的安全性和权限管理来处理暴露的端点。在上周发布的最新版本 MCP 规范(2025-03-26)中解决了这一挑战。它为客户端和服务器之间安全通信奠定了基础,利用了广泛使用的OAuth2 框架。
虽然我们不会在这篇博文中对 OAuth2 进行全面回顾,但快速复习可能会有所帮助。在规范草案中,MCP 服务器既是资源服务器又是授权服务器。
作为资源服务器,它通过检查 Authorization 头对传入请求执行授权检查。该头必须包含 OAuth2 access_token,这是一个表示客户端“权限”的字符串。该令牌可以是 JSON Web Token(JWT),也可以是不携带任何信息的不透明字符串。如果令牌缺失或无效(格式错误、已过期、收件人错误等),资源服务器将拒绝请求。使用这些令牌,典型的请求可能如下所示:
curl https://mcp.example.com/sse
-H "Authorization: Bearer <a valid access token>"
作为授权服务器,MCP 服务器还必须能够以安全的方式为客户端颁发 access_token。在颁发令牌之前,服务器将验证客户端的凭据,并在某些情况下验证尝试访问服务器的用户身份。授权服务器将决定令牌的特征:其有效期、范围、预期受众等。
使用 Spring Security 和 Spring Authorization Server,我们可以轻松地将这两种功能添加到现有的 Spring MCP 服务器中。

在此示例中,我们将向一个示例 MCP 服务器添加 OAuth 2 支持——来自我们 Spring AI 示例存储库的“天气”MCP 工具。我们不会探讨交互的客户端部分,只确保我们的服务器可以颁发和验证令牌。
首先,我们在 pom.xml 中导入所需的 Boot starters
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-authorization-server</artifactId>
</dependency>
然后,我们在 application.properties 中配置一个 OAuth2 客户端,以便我们可以请求访问令牌
spring.security.oauth2.authorizationserver.client.oidc-client.registration.client-id=mcp-client
spring.security.oauth2.authorizationserver.client.oidc-client.registration.client-secret={noop}secret
spring.security.oauth2.authorizationserver.client.oidc-client.registration.client-authentication-methods=client_secret_basic
spring.security.oauth2.authorizationserver.client.oidc-client.registration.authorization-grant-types=client_credentials
这是最简单的客户端。我们可以通过发出 POST 请求直接与授权服务器交互,无需浏览器,并使用硬编码凭据 mcp-client / secret。
最后一步是启用授权服务器和资源服务器功能。我们通过为我们的安全功能创建一个配置类来实现,例如 SecurityConfiguration,其中我们公开一个 SecurityFilterChain bean
import static org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer.authorizationServer;
@Configuration
@EnableWebSecurity
class SecurityConfiguration {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http.authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
.with(authorizationServer(), Customizer.withDefaults())
.oauth2ResourceServer(resource -> resource.jwt(Customizer.withDefaults()))
.csrf(CsrfConfigurer::disable)
.cors(Customizer.withDefaults())
.build();
}
}
此过滤器链将执行多项操作
access_token 的请求。有了这个,我们的应用程序就安全了,并且只接受带有访问令牌的请求。否则,请求将被拒绝,并显示 HTTP 401 Unauthorized 错误。例如
curl https://:8080/sse --fail-with-body
#
# Response:
#
# curl: (22) The requested URL returned error: 401
要使用我们的 MCP 服务器,我们首先需要获取一个访问令牌。我们使用 client_credentials OAuth2 授权类型,它用于“机器到机器”或“服务账户”场景
curl -XPOST https://:8080/oauth2/token --data grant_type=client_credentials --user mcp-client:secret
#
# Response:
#
# {"access_token":"<YOUR-ACCESS-TOKEN>","token_type":"Bearer","expires_in":299}%
复制 access_token 的值。它以字母“ey”开头。我们现在可以使用此访问令牌发出请求,并且它们应该会成功。例如,使用 curl,您可以将 YOUR_ACCESS_TOKEN 替换为您上面复制的值
curl https://:8080/sse -H"Authorization: Bearer YOUR_ACCESS_TOKEN"
#
# Response:
#
# id:918d5ebe-9ae5-4b04-aae8-c1ff8cdbb6e0
# event:endpoint
# data:/mcp/message?sessionId=918d5ebe-9ae5-4b04-aae8-c1ff8cdbb6e0
自版本 0.6.0 起,也可以直接在 MCP 检查器中使用访问令牌。只需启动检查器,然后将访问令牌粘贴到左侧菜单上的“Authentication > Bearer”字段中。然后单击“连接”:您应该能够进行 MCP 调用。

如果您想自己运行此示例,可以在 spring-ai-examples 仓库中查看示例代码。
在此示例中,我们已经在 MCP 服务器中实现了基础的 OAuth2 功能。
下一步显然是更新 MCP 客户端,使其能够与服务器进行身份验证,并使用“授权码”OAuth2 授权。通过这种流程,用户可以使用自己的凭据登录,并获取绑定到用户的令牌,从而实现更细粒度的权限,例如使用基于角色的访问控制(RBAC)。
我们还将探讨使用外部 OAuth2 授权服务器来颁发令牌,而只在我们的 MCP 服务器中实现资源服务器功能。