由于授权标头,Azure Blob 存储 403 身份验证失败

时间:2021-07-15 12:58:00

标签: javascript azure http-status-code-403 azure-blob-storage azure-authentication

问题

我已将一组图像(blob)上传到一个私有 Azure Blob 存储帐户,但是当我尝试访问它们时,我遇到了以下错误。


    GET https://<account-name>.blob.core.windows.net/<container-name>/<blob-name> 403 (Server failed 
    to authenticate the request. Make sure the value of Authorization header is formed correctly 
    including the signature.)

上传这些数据没有任何问题,因为这是使用 Django 应用程序通过服务器端完成的。我希望能够使用客户端 JavaScript 成功检索此上传的 blob 数据。

背景

我已通读并实施了 Microsoft Azure 文档中用于通过使用 Shared Keys 授权访问我的私人帐户的步骤。这包括从构建我的签名字符串到使用 HMAC SHA-256 算法散列此数据的所有内容,如上面的链接中所述。

我正在 Docker 容器上运行所有内容,但客户端基于 Vue 的接口尝试调用 Get Blob API 端点,如下所示。

最小可重现示例

引发此错误的代码如下:

// Add imports
const crypto = require('crypto');
const axios = require('axios');

// Set Azure blob storage data
const account = "<azure-blob-storage-private-account-name>"
const version = "2020-04-08"
const blob = "<blob-name>"
const container = "<container-name>"
const blob_uri = `https://${account}.blob.core.windows.net/${container}/${blob}`;
const today = new Date().toGMTString();
      
// Construct signature string
const CanonicalisedHeaders = `x-ms-date:${today}\nx-ms-version:${version}\n`;
const CanonicalisedResource = `/${account}/${container}/${blob}`;
const StringToSign = `GET\n\n\n\n\n\n\n\n\n\n\n\n` + CanonicalisedHeaders + CanonicalisedResource;

// Hash string using HMAC Sha-256 and encode to base64
const key = "<shared-access-key-in-base64>";
const utf8encoded = Buffer.from(key, 'base64').toString('utf8');
const signature = crypto.createHmac('sha256', utf8encoded).update(StringToSign).digest("base64");

// Construct the headers and invoke the API call
const blob_config = {
  headers: {
    "Authorization": `SharedKey ${account}:${signature}`,
    "x-ms-date": today,
    "x-ms-version": version
  }
}
await axios.get(blob_uri, blob_config)
  .then((data) => console.log(data))
  .catch((error) => console.log(error.message));

我尝试过的

我尝试了以下方法,但没有一个能帮助我解决手头的问题。

  1. 更新了 CORS 设置以避免与 CORS 相关的 403 禁止访问问题。 CORS Settings
  2. 重新生成了我的密钥和连接字符串。
  3. 检查了本地机器和 Docker 容器上的 DateTime 设置,以确保它们处于正确的 GMT 时间。
  4. 检查我的签名字符串的组件(规范化的标头、资源等)是否是根据定义的规则 here 构建的。
  5. 通读类似的 StackOverflow 和 Azure 论坛帖子以寻找解决方案。

1 个答案:

答案 0 :(得分:3)

请尝试更改以下代码行:

const utf8encoded = Buffer.from(key, 'base64').toString('utf8');
const signature = crypto.createHmac('sha256', utf8encoded).update(StringToSign).digest("base64");

const keyBuffer = Buffer.from(key, 'base64');
const signature = crypto.createHmac('sha256', keyBuffer).update(StringToSign).digest("base64");

我认为您不需要将密钥缓冲区转换为 UTF8 编码的字符串。

其他一些事情:

  1. 考虑到您是在浏览器中使用它,当您向用户公开存储密钥时存在巨大的安全风险。
  2. 您是否有理由直接使用 REST API 而不是使用 Azure Storage Blob SDK
  3. 在基于浏览器的环境中,您应该使用基于 Shared Access Signature 的授权,而不是基于 Shared Access Key 的授权。