Skip to main content

MCP 服务认证

背景:MCP Server 服务,只为携带特定请求头 token 的提供服务

示例代码

server

pom 依赖

<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webflux</artifactId>
</dependency>
</dependencies>

application 文件

server:
port: 20000

spring:
application:
name: mcp-auth-web-server
ai:
mcp:
server:
name: streamable-mcp-server
protocol: STREAMABLE # SSE、STREAMABLE、STATELESS
version: 1.0.0
type: ASYNC # Recommended for reactive applications
instructions: "This reactive server provides time information tools and resources"
request-timeout: 20s
streamable-http:
mcp-endpoint: /mcp
keep-alive-interval: 30s
disallow-delete: false

过滤器链(核心)

@Component
public class McpServerFilter implements WebFilter {

private static final String TOKENHEADER = "token-1";
private static final String TOKENVALUE = "yingzi-1";

private static final Logger logger = LoggerFactory.getLogger(McpServerFilter.class);

@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
// 获取请求头中的token值
HttpHeaders headers = exchange.getRequest().getHeaders();
// 打印所有请求头信息
for (String headerName : headers.keySet()) {
logger.info("Header {}: {}", headerName, headers.getFirst(headerName));
}

String token = headers.getFirst(TOKENHEADER);
// 检查token是否存在且值正确
if (TOKENVALUE.equals(token)) {
logger.info("preHandle: 验证通过");
logger.info("preHandle: 请求的URL: {}", exchange.getRequest().getURI());
logger.info("preHandle: 请求的TOKEN: {}", token);
// token验证通过,继续处理请求
return chain.filter(exchange);
} else {
// token验证失败,返回401未授权错误
logger.warn("Token验证失败: 请求的URL: {}, 提供的TOKEN: {}", exchange.getRequest().getURI(), token);
logger.warn("要求的token为:{}", TOKENVALUE);
exchange.getResponse().setStatusCode(org.springframework.http.HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
}
}

实现 WebFilter,只对存在请求头 token-1,且只为 yingzi-1 的连接放行。

client

pom 依赖

<dependencies>

<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>

<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
</dependency>

</dependencies>

application 文件

server:
port: 19100

spring:
application:
name: mcp-auth-client
main:
web-application-type: none
ai:
dashscope:
api-key: ${AIDASHSCOPEAPIKEY}

mcp:
client:
enabled: true
name: my-mcp-client
version: 1.0.0
request-timeout: 600s
type: ASYNC # or ASYNC for reactive applications
streamable-http:
connections:
server1:
url: http://localhost:20000
endpoint: /mcp

HTTP 请求配置

自定义 McpSyncHttpClientRequestCustomizer 接口类,为 HttpRequest.Builder 配置请求头信息

public class HeaderSyncHttpRequestCustomizer implements McpSyncHttpClientRequestCustomizer {

private final Map<String, String> headers;

public HeaderSyncHttpRequestCustomizer(Map<String, String> headers) {
this.headers = headers;
}

@Override
public void customize(HttpRequest.Builder builder, String method, URI endpoint, String body, McpTransportContext context) {
headers.forEach(builder::header);
}
}

@Configuration
public class HttpClientConfig {

@Bean
public McpSyncHttpClientRequestCustomizer mcpAsyncHttpClientRequestCustomizer() {
Map<String, String> headers = new HashMap<>();
headers.put("token-1", "yingzi-1");
headers.put("token-2", "yingzi-2");

return new HeaderSyncHttpRequestCustomizer(headers);
}
}

验证

当 mcp client 侧携带对应请求头 kv 对{token-1:yingzi-1}时,通过,否则将不予连接 mcp-auth-1

mcp-auth-2

Spring AI Alibaba 开源项目基于 Spring AI 构建,是阿里云通义系列模型及服务在 Java AI 应用开发领域的最佳实践,提供高层次的 AI API 抽象与云原生基础设施集成方案,帮助开发者快速构建 AI 应用。