前言
现Spring AI MCP需要支持授权能力,官方在2025-03-26提供了OAuth2协议的授权支持,具体参考文档。由于spring完善的生态,可以使用oauth2-resource-server和oauth2-authorization-server组件提供mcp server的oauth2的鉴权流程。官方提供了一个简单的例子。
官方博客:https://spring.io/blog/2025/04/02/mcp-server-oauth2
官方例子:https://github.com/spring-projects/spring-ai-examples/blob/main/model-context-protocol/weather/starter-webmvc-oauth2-server
需要注意:当前只支持spring-ai-mcp-server-webmvc-spring-boot-starter暂时不支持spring-ai-mcp-server-webflux-spring-boot-starter!!!
OAuth2.0授权流程
由于官方提供的例子是MCP Server本来就是Oauth的授权方,下图直接使用MCP官方文档中的2.5章节的图。
Demo测试
1,添加依赖
# spring boot版本要3.4.5以上
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
# mcp server依赖,当前只能支持webmvc,webflux不起效果。
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
</dependency>
# oauth2依赖
<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>
2,添加配置文件
# 不走浏览器的鉴权流程。直接使用硬编码。正常的流程需要走浏览器登录获得。
# client-id和client-secret这里使用硬编码
spring.security.oauth2.authorizationserver.client.oidc-client.registration.client-id=xxx
spring.security.oauth2.authorizationserver.client.oidc-client.registration.client-secret={noop}xxx
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
#spring.security.oauth2.authorizationserver.endpoint.token-uri=/mcp/oauth2/token
3,编写代码
创建一个SecurityConfiguration安全配置类。
import static org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer.authorizationServer;
@Configuration
@EnableWebSecurity
public class SecurityConfiguration {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http.authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
.with(authorizationServer(), Customizer.withDefaults())
//--启用 Spring 授权服务器和 Spring 资源服务器。
.oauth2ResourceServer(resource -> resource.jwt(Customizer.withDefaults()))
.csrf(CsrfConfigurer::disable)//--关闭 CSRF(跨站请求伪造)。MCP 服务器并非为基于浏览器的交互而设计,因此不需要 CSRF。
.cors(Customizer.withDefaults())//--开启 CORS(跨域资源共享)支持,以便我们可以使用 MCP 检查器对服务器进行演示。
.build();
}
@Value("${spring.security.oauth2.authorizationserver.client.oidc-client.registration.client-id}")
private String clientId;
@Value("${spring.security.oauth2.authorizationserver.client.oidc-client.registration.client-secret}")
private String clientSecret;
@Bean
public RegisteredClientRepository registeredClientRepository() {
//--OAuth2客户端
RegisteredClient mcpClient = RegisteredClient.withId(UUID.randomUUID().toString())
.clientId(clientId) //--硬编码的clientId
.clientSecret(clientSecret)//--硬编码的clientSecret
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
.tokenSettings(TokenSettings.builder()
.accessTokenTimeToLive(Duration.ofHours(1))//--token过期时间
.build())
.clientSettings(ClientSettings.builder()
.requireAuthorizationConsent(false)
.build())
.scope("LIST")
.build();
//--这里使用InMemoryRegisteredClientRepository,如果是正式环境,建议写到redis或者mysql中。
return new InMemoryRegisteredClientRepository(mcpClient);
}
}
4,测试
启动MCP Server服务。
a)获得Token
curl --location 'http://localhost:8115/oauth2/token' \
--data-urlencode 'grant_type=client_credentials'
b)请求MCP Server
curl --location 'http://localhost:8115/sse' \
--header 'Authorization: Bearer <ACCESS_TOKEN>'
使用错误的token或无token的情况下会报401无权错误。
使用上文中获得的正确的token。
可以看到,在添加oauth2.0的鉴权后,mcp client必须要先通过授权接口获得token才能请求mcp server,否则会出现401的无权错误。
总结
1,官方提供的博客和例子能mcp server使用oauth2.0协议授权,验证只支持webmvc,不支持webflux。
2,mcp server添加oauth2.0协议后,需要客户端先通过/oauth2/token接口获得token,然后在请求mcp server的所有接口。
3,当前spring ai mcp只支持服务端接入oauth2.0,而spring ai client由于mcp javasdk不支持,要么改源码,要么就需要等官方的版本。
4,官方demo使用InMemoryRegisteredClientRepository,生产需要自己写到redis或者mysql中。