前端从Azure Service Bus主题获取通知遇401错误求指导
核心问题梳理
你两次尝试的代码都存在关键错误,导致认证失败:
初始代码的明显错误
- 域名拼写错误:
windoes.net应为windows.net,这会直接导致请求地址无效 - Authorization 头格式错误:直接传入 accesskey 不符合 Azure Service Bus 的 SharedAccessSignature 规范,必须生成包含签名、过期时间、密钥名称的完整签名串
更新后代码的核心问题
- 签名算法错误:需使用带密钥的 HMAC-SHA256,而非普通 SHA256。Azure 要求用共享访问密钥对指定内容进行 HMAC 加密
- 待签名内容格式错误:待签名的 URL 需保留完整的
https://前缀,且签名串中的资源标识符(sr)必须是 URL 编码后的完整资源地址 - 签名串格式错误:参数分隔符使用错误,
$sr={3}应为&sr={3} - 签名编码错误:生成的签名需先转 Base64 再进行 URL 编码,而非直接转字符串
修正后的完整代码
import axios from 'axios'; import { HmacSHA256, enc } from 'crypto-js'; const sbName = 'my-sb-name'; const topicName = 'my-topic-name'; const sharedAccessKey = 'my-shared-access-key'; const sharedAccessName = 'RootManagerSharedAccessKey'; const subscriptionId = 'my-subscription-id'; // 如果要获取订阅详情需添加 // 生成过期时间(1小时后,单位:秒) const expiry = Math.floor(Date.now() / 1000) + 3600; // 完整资源URI(如果要获取订阅详情,替换为 `${baseUrl}/${topicName}/subscriptions/${subscriptionId}`) const resourceUri = `https://${sbName}.servicebus.windows.net/${topicName}`; // 构造待签名字符串 const stringToSign = `${resourceUri}\n${expiry}`; // 生成HMAC-SHA256签名 → 转Base64 → URL编码 const signature = HmacSHA256(stringToSign, sharedAccessKey).toString(enc.Base64); const encodedSignature = encodeURIComponent(signature); // 资源URI需URL编码后作为sr参数值 const encodedResourceUri = encodeURIComponent(resourceUri); // 构造符合规范的SharedAccessSignature const auth = `SharedAccessSignature sr=${encodedResourceUri}&sig=${encodedSignature}&se=${expiry}&skn=${sharedAccessName}`; const headers = { Authorization: auth, 'Content-Type': 'application/json', }; const getTopicDetails = async () => { try { const response = await axios.get(resourceUri, { headers }); console.log('主题详情:', response.data); } catch (error) { console.error('获取主题详情失败:', error.response?.data || error.message); } }; export default getTopicDetails;
重要注意事项
- 前端密钥风险:生产环境中禁止在前端代码中暴露 RootManagerSharedAccessKey,建议通过后端代理请求,或改用 Azure AD OAuth2 令牌进行认证
- webpack 兼容方案:如果想回到使用
@azure/service-bus库,可在 webpack 配置中添加 Node.js 模块 fallback:
同时安装依赖:// webpack.config.js module.exports = { resolve: { fallback: { "os": require.resolve("os-browserify/browser"), "fs": false, "path": require.resolve("path-browserify") } } };npm install os-browserify path-browserify --save-dev
内容的提问来源于stack exchange,提问作者sabarinath
相关产品推荐
相关产品推荐

