你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
本文介绍如何对 Azure 容器应用上运行的 MCP 服务器进行身份验证和保护。 方法因是托管 独立容器应用 还是在动态会话中使用 平台管理的 MCP 服务器 而异。
先决条件
- 拥有有效订阅的 Azure 帐户。 免费创建一个。
- Azure CLI 2.62.0 或更高版本。
- 现有的容器应用或会话池。 如果您没有,请参阅 MCP 服务器教程。
身份验证模型概述
Azure 容器应用支持 MCP 服务器的两种身份验证模型。 下表汇总了主要差异。
| 方面 | 独立容器应用 | 动态会话 MCP |
|---|---|---|
| 身份验证机制 | 使用 Microsoft Entra ID 的容器应用内置身份验证 |
x-ms-apikey 标头中的 API 密钥 |
| 令牌类型 | OAuth 2.0 持有者令牌 | 不透明 API 密钥字符串 |
| 身份认证服务提供商 | Microsoft Entra ID | Azure Resource Manager |
| 密钥/令牌轮换 | 由 Microsoft Entra ID 管理 | 通过 Azure 资源管理器 API 重新生成 |
| 授权范围 | 每个应用程序均可配置 | 会话池级别 |
| 传输加密 | TLS (容器应用入口) | TLS (容器应用会话终结点) |
具有 Microsoft Entra ID 身份验证的独立容器应用
将自己的 MCP 服务器部署为容器应用时,你拥有身份验证层。 使用Microsoft Entra ID 支持的容器应用 内置身份验证 功能。
配置内置身份验证
以下步骤注册Microsoft Entra ID 应用程序并在容器应用中启用内置身份验证。
在 Microsoft Entra ID 中注册应用程序:
APP_ID=$(az ad app create \ --display-name "mcp-server-auth" \ --sign-in-audience AzureADMyOrg \ --query appId -o tsv)创建服务主体:
az ad sp create --id $APP_ID添加客户端密码:
CLIENT_SECRET=$(az ad app credential reset --id $APP_ID --query password -o tsv) TENANT_ID=$(az account show --query tenantId -o tsv)在容器应用上启用内置身份验证:
az containerapp auth microsoft update \ --name <CONTAINER_APP_NAME> \ --resource-group <RESOURCE_GROUP> \ --client-id $APP_ID \ --client-secret $CLIENT_SECRET \ --tenant-id $TENANT_ID \ --issuer "https://login.microsoftonline.com/$TENANT_ID/v2.0" \ --yes将未经身份验证的动作设置为需要登录:
az containerapp auth update \ --name <CONTAINER_APP_NAME> \ --resource-group <RESOURCE_GROUP> \ --unauthenticated-client-action Return401
使用持有者令牌从 MCP 客户端进行连接
当 MCP 服务器需要持有者令牌时,请在 MCP 客户端中配置令牌检索。 以下是 GitHub Copilot 的 .vscode/mcp.json 配置示例:
{
"servers": {
"my-mcp-server": {
"type": "http",
"url": "https://<CONTAINER_APP_NAME>.<REGION>.azurecontainerapps.io/mcp",
"headers": {
"Authorization": "Bearer ${input:mcpBearerToken}"
}
}
},
"inputs": [
{
"id": "mcpBearerToken",
"type": "promptString",
"description": "Enter your bearer token for the MCP server",
"password": true
}
]
}
小窍门
在开发环境中,使用 az account get-access-token --resource $APP_ID --query accessToken -o tsv 获取令牌,并在提示时粘贴该令牌。 对于自动化工作流,请与组织的令牌管理系统集成。
配置 CORS
从基于 Web 的环境连接的 MCP 客户端需要 CORS 标头。 使用以下命令在容器应用中配置 CORS:
az containerapp ingress cors update \
--name <CONTAINER_APP_NAME> \
--resource-group <RESOURCE_GROUP> \
--allowed-origins "https://vscode.dev" "https://github.dev" \
--allowed-methods "GET" "POST" "OPTIONS" \
--allowed-headers "Content-Type" "Authorization" "Mcp-Session-Id" \
--max-age 3600
以下标头对于允许是关键的:
-
Content-Type:JSON-RPC 请求所必需的 -
Authorization:持有者令牌身份验证所必需的 -
Mcp-Session-Id:MCP 客户端用于有状态会话
注释
GitHub Copilot 通过 VS Code 桌面应用进行连接,而不是通过浏览器连接至远程 MCP 服务器。 仅当你打算支持基于浏览器的 MCP 客户端或 Web 的 VS Code 时,才需要 CORS。 独立教程为简化起见使用通配符 CORS 源;在生产环境中,请按此处所示限制为特定的受信任源。
独立 MCP 服务器的安全建议
应用以下最佳做法来强化独立的 MCP 服务器。
- 网络限制:使用 IP 限制 或 虚拟网络集成 来限制对已知客户端 IP 的访问。
- 速率限制:在应用程序代码中实施速率限制,或使用 Azure API 管理在应用前面实现速率限制。
- 输入验证:验证 MCP 服务器代码中的所有工具参数。 MCP 工具输入是任意 JSON。 将它们视为不受信任。
-
无状态设计:首选无状态 MCP 服务器以避免会话劫持风险。 在大多数 MCP SDK 中,这意味着禁用服务器端会话 ID 生成(例如,
sessionIdGenerator: undefined在 TypeScript 或stateless_http=TruePython 中)。 -
运行状况探测:在单独的终结点(例如
/healthz),而不是 MCP 终结点上配置运行状况探测。 MCP 终结点需要 JSON-RPC POST 请求,对于普通的 GET 探测会返回错误。
使用 API 密钥身份验证的动态会话
重要
动态会话的平台托管 MCP 服务器处于 预览状态。 API 版本 2025-02-02-preview 和 mcpServerSettings 属性可能会更改。
动态会话中的平台管理的 MCP 服务器使用 API 密钥身份验证。 密钥的范围限定为会话池,并授予对池中的所有工具和会话的访问权限。
API 密钥身份验证流
以下步骤介绍了 API 密钥身份验证如何适用于动态会话。
- 客户端发送具有
x-ms-apikey标头的 JSON-RPC 请求。 - 会话池代理根据 Azure 控制平面验证密钥。
- 如果密钥有效,则请求将转发到会话。 否则,将返回身份验证错误。
检索 API 密钥
使用以下命令提取会话池的 API 密钥。
API_KEY=$(az rest --method POST \
--uri "https://management.azure.com/subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP>/providers/Microsoft.App/sessionPools/<SESSION_POOL_NAME>/fetchMCPServerCredentials" \
--uri-parameters api-version=2025-02-02-preview \
--query "apiKey" -o tsv)
轮换和缓存 API 密钥
可以随时重新生成 API 密钥。 平台缓存验证结果最多 5 分钟,因此在重新生成后,以前有效的密钥可能会继续工作,直到缓存过期。
若要轮换 API 密钥,请调用会话池中的 regenerateCredentials 操作。
az rest --method POST \
--uri "https://management.azure.com/subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP>/providers/Microsoft.App/sessionPools/<SESSION_POOL_NAME>/regenerateCredentials" \
--uri-parameters api-version=2025-02-02-preview
重新生成后,使用 fetchMCPServerCredentials 如前所示检索新密钥。
动态会话的安全建议
应用以下最佳做法来保护动态会话 MCP 部署。
- API 密钥范围:API 密钥授予对整个会话池的访问权限。 具有密钥的任何客户端都可以创建环境和执行代码。 不要与不受信任的参与方共享密钥。
- 环境隔离:每个会话在 Hyper-V 隔离的容器中运行。 一个会话中的代码执行无法访问另一个会话的数据。
-
网络出口:使用
sessionNetworkConfiguration.status控制会话是否可以访问 Internet。 如果会话不需要外部网络访问,则设置为EgressDisabled。 -
会话生存期:配置为
coolDownPeriodInSeconds自动销毁空闲会话。 如果会话遭到入侵,此设置将限制公开窗口。 - 机密存储:将 API 密钥存储在 Azure Key Vault 或 容器应用机密 中,而不是存储在代码或配置文件中。
常见的身份验证不匹配
常见的错误是将 API 密钥标头(x-ms-apikey)与独立容器应用一起使用,或使用具有会话 MCP 终结点的持有者令牌。 下表显示了混合它们时会发生什么情况。
| Mismatch | 结果 |
|---|---|
x-ms-apikey 发送到独立应用的 标头 |
忽略标头;请求触发内置身份验证,并在启用身份验证时返回401 |
Authorization: Bearer 发送到会话 MCP |
密钥验证失败并返回 401 |
确保 MCP 客户端配置与部署的托管模型匹配。