Java MCP 鑒權(quán)設(shè)計(jì)與實(shí)現(xiàn)指南(完整示例)
一、MCP 鑒權(quán)概述
MCP (Model Context Protocol) 旨在為大語(yǔ)言模型(LLM)與外部數(shù)據(jù)源、工具和服務(wù)提供標(biāo)準(zhǔn)化、安全的集成方式(相當(dāng)于一種專用的 RPC 協(xié)議)。廣泛應(yīng)用于 AI 開發(fā)中的工具服務(wù)(Tool)、提示語(yǔ)服務(wù)(Prompt)和資源服務(wù)(Resource)。在實(shí)際應(yīng)用中,確保 MCP 服務(wù)的安全性至關(guān)重要,因此需要合理的鑒權(quán)機(jī)制。
根據(jù)提供的資料,MCP 鑒權(quán)主要涉及以下幾個(gè)方面:
- 服務(wù)端鑒權(quán)設(shè)計(jì)
- 客戶端鑒權(quán)配置
- 不同通訊通道(stdio/SSE)的鑒權(quán)實(shí)現(xiàn)
- 與 Web API 互通的鑒權(quán)處理
本案基于 Solon AI MCP 進(jìn)行鑒權(quán)方面的探討:
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon-ai-mcp</artifactId>
<version>最新版本</version>
</dependency>可支持 java8, java11, java17, java21, java24 。可支持 solon,springboot,vert.x,jFinal 等框架集成。
二、MCP 服務(wù)端鑒權(quán)設(shè)計(jì)
1、基于過濾器的鑒權(quán)方案
MCP 服務(wù)端可以通過過濾器或路由攔截器實(shí)現(xiàn)鑒權(quán),特別是對(duì)于 HTTP SSE 通道的服務(wù):
@Component
public class McpFilter implements Filter {
@Override
public void doFilter(Context ctx, FilterChain chain) throws Throwable {
//message 端點(diǎn),不需要鑒權(quán)
if (ctx.pathNew().startsWith("/mcp/") && ctx.pathNew().endsWith("/message") == false) {
String authStr = ctx.header("Authorization");
if (Utils.isEmpty(authStr)) {
ctx.status(401);
return;
}
// 業(yè)務(wù)檢測(cè)邏輯
if (!checkAuth(authStr)) {
ctx.status(403);
return;
}
}
chain.doFilter(ctx);
}
private boolean checkAuth(String authStr) {
// 實(shí)現(xiàn)具體的鑒權(quán)邏輯
return true;
}
}2、基于注解的端點(diǎn)級(jí)鑒權(quán)
對(duì)于使用 @McpServerEndpoint 注解的服務(wù)端點(diǎn),可以通過 @Header 注解或者 上下文對(duì)象(Context) 獲取用戶身份或鑒權(quán)信息:
@McpServerEndpoint(sseEndpoint = "/mcp/sse")
public class McpAuthService {
@ToolMapping(description = "需要鑒權(quán)的天氣預(yù)報(bào)查詢")
public String getWeather(@Param(description = "城市位置") String location, @Header("user") user, Context ctx) {
// 根據(jù)用戶隔離數(shù)據(jù): user
// 從上下文中獲取鑒權(quán)或身份信息: ctx
return "晴,14度";
}
}在方法里鑒權(quán)時(shí)不能輸出狀態(tài)碼,要改為異常拋出。
三、MCP 客戶端鑒權(quán)配置
1、Basic Authentication
McpClientProvider toolProvider = McpClientProvider.builder()
.apiUrl("https://localhost:8080/mcp/sse")
.apiKey("sk-xxxxx") // 自動(dòng)轉(zhuǎn)換為Authorization頭
.build();2、自定義 Header 鑒權(quán)
McpClientProvider toolProvider = McpClientProvider.builder()
.apiUrl("https://localhost:8080/mcp/sse")
.header("X-API-KEY", "your-api-key")
.header("X-API-SECRET", "your-api-secret")
.header("X-USER", "your-user")
.build();3、QueryString 參數(shù)鑒權(quán)(比較常見)
McpClientProvider toolProvider = McpClientProvider.builder()
.apiUrl("https://localhost:8080/mcp/sse?token=xxxx")
.build();四、不同通道的鑒權(quán)實(shí)現(xiàn)
1、HTTP SSE 通道鑒權(quán)
HTTP SSE 通道的鑒權(quán)可以利用 HTTP 協(xié)議本身的特性:
@Configuration
public class McpSseAuthConfig {
@Bean
public McpClientProvider sseClient() {
return McpClientProvider.builder()
.apiUrl("http://localhost:8080/mcp/sse")
.header("X-Auth-Token", "your-token")
.httpTimeout(HttpTimeout.builder()
.connectTimeout(Duration.ofSeconds(10))
.readTimeout(Duration.ofSeconds(60))
.build())
.build();
}
}2、2. STDIO 通道鑒權(quán)
對(duì)于 STDIO 通道,鑒權(quán)通常通過環(huán)境變量或啟動(dòng)參數(shù)實(shí)現(xiàn):
@McpServerEndpoint(channel = McpChannel.STDIO)
public class StdioAuthService {
@ToolMapping(description = "STDIO通道的鑒權(quán)服務(wù)")
public String secureOperation(@Param String input) {
String authToken = System.getenv("INTERNAL_AUTH_TOKEN");
if(!validateInternalToken(authToken)) {
throw new SecurityException("Invalid internal token");
}
return processInput(input);
}
}客戶端調(diào)用時(shí)配置環(huán)境變量:
McpClientProvider stdioClient = McpClientProvider.builder()
.channel(McpChannel.STDIO)
.serverParameters(ServerParameters.builder("java")
.args("-jar", "secure-service.jar")
.addEnvVar("INTERNAL_AUTH_TOKEN", "secure-token-value")
.build())
.build();五、與 Web API 互通的鑒權(quán)
MCP 服務(wù)可以與 Web API 互通,共享鑒權(quán)邏輯:
@Mapping("/api/secure")
@Controller
@McpServerEndpoint(sseEndpoint = "/mcp/secure/sse")
public class HybridAuthService {
@ToolMapping(description = "混合鑒權(quán)服務(wù)")
@Mapping("operation")
public String hybridOperation(
@Param(description = "輸入?yún)?shù)") String input,
@Header("Authorization") String authHeader) {
if(!validateAuthHeader(authHeader)) {
throw new SecurityException("Unauthorized");
}
return "Processed: " + input;
}
}六、最佳實(shí)踐與注意事項(xiàng)
多因素認(rèn)證:對(duì)于高安全性要求的場(chǎng)景,可以結(jié)合多種鑒權(quán)方式
McpClientProvider highSecClient = McpClientProvider.builder()
.apiUrl("https://secure.example.com/mcp/sse")
.apiKey("primary-key")
.header("X-Second-Factor", "totp-code")
.build();敏感信息保護(hù):避免在日志中輸出鑒權(quán)信息
// 開發(fā) stdio 服務(wù)時(shí)特別重要
@McpServerEndpoint(channel = McpChannel.STDIO)
public class SecureStdioService {
// 確保不打印敏感信息到控制臺(tái)
}性能考慮:對(duì)于高頻調(diào)用的服務(wù),采用高效的鑒權(quán)方案
// 使用高效的JWT驗(yàn)證
public class JwtAuthFilter implements Filter {
// 實(shí)現(xiàn)快速的JWT驗(yàn)證邏輯
}七、完整示例:帶鑒權(quán)的 MCP 服務(wù)
服務(wù)端實(shí)現(xiàn)
// 鑒權(quán)配置類
@Configuration
public class McpAuthConfig {
@Bean
public Filter mcpAuthFilter() {
return new McpAuthFilter();
}
}
// 鑒權(quán)過濾器
public class McpAuthFilter implements Filter {
@Override
public void doFilter(Context ctx, FilterChain chain) throws Throwable {
if (ctx.pathNew().startsWith("/mcp/") && ctx.pathNew().endsWith("/message") == false) {
String token = ctx.header("X-Auth-Token");
if (!"valid-token".equals(token)) {
ctx.status(401).output("Unauthorized");
return;
}
}
chain.doFilter(ctx);
}
}
// MCP服務(wù)端點(diǎn)
@McpServerEndpoint(sseEndpoint = "/mcp/secure/sse")
public class SecureMcpService {
@ToolMapping(description = "安全操作")
public String secureOp(@Param(description = "輸入") String input) {
return "Secure result for: " + input;
}
}客戶端實(shí)現(xiàn)
public class SecureMcpClient {
private final McpClientProvider client;
public SecureMcpClient() {
this.client = McpClientProvider.builder()
.apiUrl("http://localhost:8080/mcp/secure/sse")
.header("X-Auth-Token", "valid-token")
.requestTimeout(Duration.ofSeconds(20))
.build();
}
public String callSecureOp(String input) {
return client.callToolAsText("secureOp", Map.of("input", input));
}
}總結(jié)
MCP 鑒權(quán)是保障服務(wù)安全性的重要環(huán)節(jié),通過本文介紹的服務(wù)端過濾器、客戶端配置、不同通道實(shí)現(xiàn)等方式,可以構(gòu)建靈活安全的鑒權(quán)體系。在實(shí)際應(yīng)用中,應(yīng)根據(jù)具體場(chǎng)景選擇適合的鑒權(quán)方案,并遵循安全最佳實(shí)踐,確保 MCP 服務(wù)的安全可靠運(yùn)行。
到此這篇關(guān)于Java MCP 鑒權(quán)設(shè)計(jì)與實(shí)現(xiàn)指南的文章就介紹到這了,更多相關(guān)Java MCP 鑒權(quán)設(shè)計(jì)與實(shí)現(xiàn)指南內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
spring使用@Async注解導(dǎo)致循環(huán)依賴問題異常的排查記錄
這篇文章主要介紹了spring使用@Async注解導(dǎo)致循環(huán)依賴問題異常的排查記錄,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
ThreadLocal簡(jiǎn)介_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要為大家詳細(xì)介紹了ThreadLocal簡(jiǎn)介的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08
Springboot項(xiàng)目全局異常統(tǒng)一處理案例代碼
最近在做項(xiàng)目時(shí)需要對(duì)異常進(jìn)行全局統(tǒng)一處理,主要是一些分類入庫(kù)以及記錄日志等,因?yàn)轫?xiàng)目是基于Springboot的,所以去網(wǎng)絡(luò)上找了一些博客文檔,然后再結(jié)合項(xiàng)目本身的一些特殊需求做了些許改造,現(xiàn)在記錄下來便于以后查看2023-01-01
SpringBoot中關(guān)于static和templates的注意事項(xiàng)以及webjars的配置
今天小編就為大家分享一篇關(guān)于SpringBoot中關(guān)于static和templates的注意事項(xiàng)以及webjars的配置,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-01-01
SpringBoot實(shí)現(xiàn)接受文件和對(duì)象
SpringBoot中接受文件和對(duì)象的場(chǎng)景,推薦使用`multipart/form-data`格式,后端可以通過接受實(shí)體并將文件放入對(duì)象屬性中來處理數(shù)據(jù),使用`@Validated`注解進(jìn)行參數(shù)校驗(yàn)是可行的,但要注意不要與`@RequestBody`注解同時(shí)使用2025-12-12
Java實(shí)現(xiàn)復(fù)制文件并命名的超簡(jiǎn)潔寫法
這篇文章主要介紹了Java實(shí)現(xiàn)復(fù)制文件并命名的超簡(jiǎn)潔寫法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11

