如何安全存储Bing Speech API的SubscriptionKey?支持动态生成或过期限制吗?
安全处理Bing Speech API密钥的最佳实践
你这个问题戳中了前端调用云API的典型痛点——绝对不能把订阅密钥直接硬编码在HTML/JS代码里!只要代码能被用户看到,密钥就等于公开了,被人拿去滥用只是时间问题。下面给你讲几个靠谱的解决方案,从根本上解决这个问题:
1. 用后端代理彻底隐藏密钥(最安全的方案)
这是业界通用的标准做法:前端不直接调用Bing Speech API,而是通过你自己的后端服务器中转请求。具体流程是:
- 前端收集语音数据,把它发送到你自己的后端接口
- 后端接口使用存储在服务器端的订阅密钥,调用Bing Speech API
- 后端把API返回的识别结果再转发给前端
这样订阅密钥完全不会出现在前端代码里,只有你的后端能接触到它。举个简单的示例:
后端示例(Node.js)
const express = require('express'); const axios = require('axios'); const app = express(); app.use(express.json()); // 把订阅密钥存在环境变量里,不要硬编码! const BING_SUBSCRIPTION_KEY = process.env.BING_SPEECH_KEY; const BING_API_URL = 'https://speech.platform.bing.com/speech/recognition/conversation/cognitiveservices/v1'; app.post('/api/speech-recognition', async (req, res) => { try { const response = await axios.post(BING_API_URL, req.body, { headers: { 'Ocp-Apim-Subscription-Key': BING_SUBSCRIPTION_KEY, 'Content-Type': 'audio/wav; codec="audio/pcm"; samplerate=16000' }, params: { language: 'zh-CN', format: 'json' } }); res.json(response.data); } catch (error) { res.status(error.response.status).json(error.response.data); } }); app.listen(3000, () => console.log('Server running on port 3000'));
前端示例
// 调用自己的后端接口,不用碰密钥 async function recognizeSpeech(audioBlob) { const formData = new FormData(); formData.append('audio', audioBlob); const response = await fetch('/api/speech-recognition', { method: 'POST', body: formData }); const result = await response.json(); return result; }
2. 使用短期访问令牌替代长期订阅密钥
如果你因为某些原因必须让前端直接调用API,那绝对不要用长期订阅密钥,而是用短期访问令牌。Bing Speech API支持通过订阅密钥生成有效期较短的令牌(通常是10分钟),就算令牌泄露,危害也非常有限。
实现流程:
- 后端用订阅密钥请求Bing的令牌生成接口,获取短期令牌
- 前端向你的后端请求这个令牌,拿到后用它调用Bing Speech API
- 令牌过期后,前端再重新向后端请求新的令牌
生成令牌的后端代码示例:
app.get('/api/get-speech-token', async (req, res) => { try { const tokenResponse = await axios.post( 'https://api.cognitive.microsoft.com/sts/v1.0/issueToken', {}, { headers: { 'Ocp-Apim-Subscription-Key': BING_SUBSCRIPTION_KEY } } ); // 返回令牌和过期时间(比如10分钟后) res.json({ token: tokenResponse.data, expiresAt: Date.now() + 10 * 60 * 1000 }); } catch (error) { res.status(error.response.status).json(error.response.data); } });
前端拿到令牌后,调用API时用Authorization: Bearer <token>代替订阅密钥即可。
3. 额外的安全加固措施
- 把订阅密钥存在环境变量里:不管是后端还是任何配置文件,都不要硬编码密钥,用环境变量或者专门的配置管理工具(比如Azure Key Vault)存储。
- 限制密钥的访问范围:在Azure门户里,给你的Bing Speech资源设置IP白名单,只允许你的后端服务器IP访问,就算密钥泄露,别人也没法用。
- 启用用量监控和告警:在Azure里设置API的用量阈值,一旦超过正常使用量就触发告警,及时发现滥用行为。
要特别提醒:绝对不要尝试在前端加密密钥或者用其他“小聪明”的方法隐藏,只要代码在浏览器里运行,用户就能拿到密钥。后端代理或者短期令牌才是正道。
内容的提问来源于stack exchange,提问作者stack_user
相关产品推荐
相关产品推荐

