Blob 存储帐户的 Azure SAS 令牌不起作用

Posted

技术标签:

【中文标题】Blob 存储帐户的 Azure SAS 令牌不起作用【英文标题】:Azure SAS token for blob storage account not working 【发布时间】:2021-11-20 18:23:29 【问题描述】:

更新: 我已经更新了函数以提供广泛的时间范围以避免过期。我还包括我更新以启用公共访问的帐户设置的屏幕截图。还包括当前的控制台结果。页面上的结果相同,图片打不开。

async function sasKey(mediaLoc) 
    try 
    console.log('starting sasKey in bloboperations mediaLoc:', mediaLoc)
    console.log('process.env.BLOB_CONTAINER is: ', process.env.BLOB_CONTAINER)
    var storage = require("@azure/storage-blob")
    const accountname = process.env.BLOB_ACCT_NAME;
    console.log('accountname is: ', accountname)
    const key = process.env.BLOB_KEY;
    const cerds = new storage.StorageSharedKeyCredential(accountname,key);
    const blobServiceClient = new storage.BlobServiceClient(`https://$accountname.blob.core.windows.net`,cerds);
    const containerName=process.env.BLOB_CONTAINER;
    const client =blobServiceClient.getContainerClient(containerName)
    const blobName=mediaLoc;
    const blobClient = client.getBlobClient(blobName);
    const checkDate = new Date();
    const startDate =  new Date(checkDate.valueOf() - 1200000);
    const endDate = new Date(checkDate.valueOf() + 3600000);
    console.log('checkDate, startDate, endDate: ', checkDate, startDate, endDate)
    const blobSAS = storage.generateBlobSASQueryParameters(
      containerName, 
      blobName, 
      permissions: storage.BlobSASPermissions.parse("racwd"), 
      startsOn: startDate,
      expiresOn: endDate
    ,
    cerds 
  ).toString();
      console.log( 'blobSAS is: ', blobSAS)
 //   const sasUrl= blobClient.url+"?"+encodeURIComponent(blobSAS);
    const sasUrl = 'https://' + accountname + '/' + containerName + '/' + blobName + '?' + blobSAS
    console.log('sasURL is: ', sasUrl);

    return sasUrl
    
    catch (error) 
        console.log(error);
    

我正在尝试通过 node.js 函数从我的 Azure 存储 blob 容器中获取有效的 SAS URI。我正在使用@azure/storage-blob 库。我收到了 Azure 的回复,但浏览器说它未经授权。我已经四次检查我的帐户和密钥是否正确。这些设置正在将媒体上传到容器中。

我什至不确定如何进行故障排除,因为没有任何错误消息返回到节点 api。相同的代码返回一个在另一个(开发)容器中工作的 URI。但是,该容器现在允许公共访问。因此,无论如何,您都可以从该 blob 访问 blob 是有道理的。请对我如何解决此问题有任何建议吗?

访问控制台生成的blob报错:

5x6gyfbc5eo31fdf38f7fdc51ea1632857020560.png:1 获取 https://**********.blob.core.windows.net/prod/5x6gyfbc5eo31fdf38f7fdc51ea1632857020560.png?sv%3D2020-06-12%26st%3D2021- 09-28T19%253A23%253A41Z%26se%3D2021-09-28T19%253A25%253A07z%26SR%3DB%26SP%3DRACWD%26SIG%3DU6NAIIKN%252B825KOPIKQRGMIOOKMJZ5L3MFCR%252FTCT3UYK%253D 409(在此存储帐户中不允许公共访问)。)

生成URI的代码:

async function sasKey(mediaLoc) 
try 
var storage = require("@azure/storage-blob")
const accountname = process.env.BLOB_ACCT_NAME;
const key = process.env.BLOB_KEY;
const cerds = new storage.StorageSharedKeyCredential(accountname,key);
const blobServiceClient = new storage.BlobServiceClient(`https://$accountname.blob.core.windows.net`,cerds);
const containerName=process.env.BLOB_CONTAINER;
const client =blobServiceClient.getContainerClient(containerName)
const blobName=mediaLoc;
const blobClient = client.getBlobClient(blobName);
const blobSAS = storage.generateBlobSASQueryParameters(
  containerName, 
  blobName, 
  permissions: storage.BlobSASPermissions.parse("racwd"), 
  startsOn: new Date(),
  expiresOn: new Date(new Date().valueOf() + 86400)
,
cerds).toString();
const sasUrl= blobClient.url+"?"+encodeURIComponent(blobSAS);
console.log('blobOperations.js returns blobSAS URL as: ', sasUrl);
console.log( 'blobSAS is: ', blobSAS)
return sasUrl

catch (error) 
    console.log(error);

【问题讨论】:

报错信息Signature not valid in the specified time frame表示您电脑上的日期/时间/时区错误。 您收到此错误是因为您的 sas 令牌已过期。它在Tue, 28 Sep 2021 17:12:15 GMTTue, 28 Sep 2021 17:13:42 GMT 之间有效,但您在Tue, 28 Sep 2021 17:19:26 GMT 使用它(到期后大约6 分钟。请在到期前重新生成一个新令牌并使用它。 抱歉,这是我后来在进行故障排除时出现的问题。我刚刚更新了这个问题,以显示首次创建 SAS 时我在浏览器控制台中得到的内容。这是访问错误。对此我深表歉意。 消息“此存储帐户不允许公共访问”表示该帐户的“允许 Blob 公共访问”设置已禁用。您可以在“设置”>“配置”下的帐户门户中查看它。 @GauravMantri 和 John Hanley,感谢您的回复。不知道你有没有看到我的评论。不幸的是,我最初发布了错误的错误消息。我更新了我在问题中实际看到的问题。如果您有任何其他想法,我将不胜感激。 【参考方案1】:

经过大量的摆弄,我想出了以下在生产和开发中都可以使用的功能。我不能 100% 确定哪些变化会产生影响,但我认为有三件事很重要。首先,Joel Cochran 对了解如何设置帐户的帮助至关重要。其次,到期时间也可能是一个问题。正如您从下面的正确代码中看到的那样,我已经做出了完全不同的事情。但我认为最后一块是我使用的部分:storage.generateBlobSASQueryParameters()。

async function sasKey(mediaLoc) 
  if (process.env.SERVER_STATUS === 'Prod') 
    activeContainer = 'prod'
   else 
    activeContainer = 'dev'
  
    try 
    var storage = require("@azure/storage-blob")
    const accountname = process.env.BLOB_ACCT_NAME;
    const key = process.env.BLOB_KEY;
    const cerds = new storage.StorageSharedKeyCredential(accountname,key);
    const blobServiceClient = new storage.BlobServiceClient(`https://$accountname.blob.core.windows.net`,cerds);
    const containerName = activeContainer;
    const client =blobServiceClient.getContainerClient(containerName)
    const blobName=mediaLoc;
    const blobClient = client.getBlobClient(blobName);
    const checkDate = new Date();
    const startDate =  new Date(checkDate.valueOf() - 5*60*1000);
    const endDate = new Date(checkDate.valueOf() + + 24*60*60*1000);

     // Generate service level SAS for a blob
      const blobSAS = storage.generateBlobSASQueryParameters(
          containerName, // Required
          mediaLoc, // Required
          permissions: storage.BlobSASPermissions.parse("racwd"), // Required
          startsOn: startDate, // Required. Date type
          expiresOn: endDate // Required. Date type
        ,
        cerds // StorageSharedKeyCredential - `new StorageSharedKeyCredential(account, accountKey)`
      ).toString();
      
     sasUrl = `https://$accountname.blob.core.windows.net/$containerName/$mediaLoc?$blobSAS.toString()`;
          return sasUrl
          
          catch (error) 
              console.log(error);
          
 

注意:我使用 if 语句来设置容器,以便在测试时让我的生活更轻松。您肯定会在生产环境中使用环境变量。

非常感谢大家的支持。这是一个了不起的社区。​​p>

【讨论】:

以上是关于Blob 存储帐户的 Azure SAS 令牌不起作用的主要内容,如果未能解决你的问题,请参考以下文章

在不使用主键或辅助键的情况下使用 azure 存储帐户进行身份验证

Azure 存储帐户:Blob 服务 (SAS) 连接检查失败

有没有办法重新生成 Azure Blob 存储 SAS 令牌

Azure CDN URL使用令牌身份验证和Blob存储SAS重写规则

如何在 Azure 中的密钥轮换后为存储 Blob 的客户端请求提供服务

使用 Blob 特定的 SAS 令牌连接和更新 Azure Blob