Azure语音服务配置防火墙后无法获取临时授权令牌
问题场景
我有一个.NET Web应用正在集成Azure Speech Service,为了限制公共访问,配置了自定义域名,并在「资源管理>网络>选定网络和专用终结点」的防火墙中添加了白名单IP。目前使用JavaScript SDK通过订阅密钥调用speechConfig = sdkConfigType.fromSubscription(key, region)可以正常访问语音服务。
但出于安全考虑,前端暴露订阅密钥存在风险,因此需要改用临时授权令牌(每10分钟刷新),通过speechConfig = sdkConfigType.fromAuthorizationToken(token, region)调用。
后端通过C#代码发起HTTP请求获取令牌,代码如下:
public async Task<string> GetSpeechToken() { string tokenEndpoint = configuration.GetValue<string>("SpeechServiceEndpoint") ?? string.Empty; string subscriptionKey = configuration.GetValue<string>("SpeechServiceKey") ?? string.Empty; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", subscriptionKey); client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Region", configuration.GetValue<string>("SpeechServiceRegion")); UriBuilder uriBuilder = new(tokenEndpoint); var result = await client.PostAsync(uriBuilder.Uri.AbsoluteUri, null); var token = await result.Content.ReadAsStringAsync(); return token; }
配置信息:
{ "SpeechServiceKey": "*** <my subscription key> ***", "SpeechServiceRegion": "australiaeast", "SpeechServiceEndpoint": "https://<my custom domain>.cognitiveservices.azure.com/sts/v1.0/issueToken" }
遇到的问题
上述HTTP请求始终返回400错误:Virtual network/Firewall is configured, Token API is disabled.。即使将端点替换为区域端点https://australiaeast.api.cognitive.microsoft.com/sts/v1.0/issueToken,错误依然存在。
当前Azure语音服务的网络配置截图:
原因分析
Azure Speech Service在启用防火墙/虚拟网络访问限制后,STS令牌颁发API(sts/v1.0/issueToken)会被默认禁用。该API不支持基于IP的访问控制规则,即使后端服务器IP在白名单中,也无法通过防火墙限制的资源访问此端点。
解决方案
方案1:使用托管标识获取令牌(推荐)
改用Azure托管标识获取Speech Service访问令牌,绕过STS端点的限制,同时提升安全性:
- 在Azure门户为.NET Web应用的宿主(如App Service、虚拟机)启用系统分配托管标识
- 为该托管标识授予Speech Service的Cognitive Services Speech User角色(或更高权限的RBAC角色)
- 修改后端代码,使用Azure Identity SDK获取令牌:
using Azure.Identity; using Azure.Core; public async Task<string> GetSpeechToken() { string resourceScope = "https://cognitiveservices.azure.com/.default"; var credential = new DefaultAzureCredential(); var tokenRequest = new TokenRequestContext(new[] { resourceScope }); var tokenResult = await credential.GetTokenAsync(tokenRequest, CancellationToken.None); return tokenResult.Token; }
此方式无需存储订阅密钥,依托Azure RBAC控制访问权限,完全兼容防火墙/虚拟网络限制。
方案2:临时允许所有网络访问STS端点(仅测试用)
如果仅需临时测试令牌功能,可临时放宽网络限制:
- 进入Azure Speech Service的「网络」设置
- 在「防火墙」部分勾选允许从所有网络访问
- 注意:此操作会降低资源安全性,生产环境禁止使用
方案3:通过专用终结点访问STS(安全但配置复杂)
为Speech Service创建专用终结点,将STS端点流量限制在虚拟网络内部:
- 在Azure门户为Speech Service创建专用终结点,关联到你的虚拟网络
- 确保后端应用部署在同一虚拟网络,或通过VPN/ExpressRoute连接到该网络
- 修改后端代码中的STS端点为专用终结点的域名
内容的提问来源于stack exchange,提问作者OjM

