【问题标题】:How to generate Account SAS token for Azure Storage?如何为 Azure 存储生成帐户 SAS 令牌?
【发布时间】:2020-03-08 15:58:27
【问题描述】:

理想情况下,我想访问存储中的所有容器和 blob。 Account SAS 令牌是在我的代码中生成的服务器端。客户端将调用我在 Node.js 中创建的 API 来接收它。我看到您可以使用 Azure Shell 手动创建 SAS 令牌,但我更喜欢让它在服务端生成,因为将实施身份验证。

account SAS generation documentation 之后,它声明字符串到签名应该这样构造。

StringToSign = accountname + "\n" +  
    signedpermissions + "\n" +  
    signedservice + "\n" +  
    signedresourcetype + "\n" +  
    signedstart + "\n" +  // optional
    signedexpiry + "\n" +  
    signedIP + "\n" +  // optional
    signedProtocol + "\n" +  // optional
    signedversion + "\n" 

文档中的示例令牌(分成多行以提高可见性)

sv=2019-02-02&ss=bf&srt=s&st=2019-08-01T22%3A18%3A26Z
&se=2019-08-10T02%3A23%3A26Z&sr=b&sp=rw
&sip=168.1.5.60-168.1.5.70&spr=https
&sig=F%6GRVAZ5Cdj2Pw4tgU7IlSTkWgn7bUkkAg8P6HESXwmf%4B

从 Azure Shell 生成的令牌

se=2019-11-15&sp=rwdlac&sv=2018-03-28&ss=b&srt=sco&sig=<hidden signature>

奇怪的是,在示例令牌中,首先提供的是 signedversion (sv),而 Azure Shell 的令牌中是 signedexpiry (se)

以下是用于生成令牌的代码。我尝试遵循与 Azure Shell 中的令牌相同的顺序:

app.get('/sas-token', (req, res, next) => {

  // const start = new Date(new Date().getTime() - (15 * 60 * 1000));
  const end = new Date(new Date().getTime() + (30 * 60 * 1000));

  const signedpermissions = 'rwdlac';
  const signedversion = '2018-03-28';
  const signedservice = 'b';
  const signedresourcetype = 'sco';
  // const signedstart = truncateIsoDate(start);
  const signedexpiry = truncateIsoDate(end);
  // const signedIP = '';
  const signedProtocol = 'https';

  const StringToSign = STORAGE_ACCOUNT_NAME + "\n" +
      signedpermissions + "\n" +
      signedservice + "\n" +
      signedresourcetype + "\n" +
      // signedstart + "\n" +  
      signedexpiry + "\n" +
      // signedIP + "\n" +  
      signedProtocol + "\n" +
      signedversion + "\n"

  const key = new Buffer(ACCOUNT_ACCESS_KEY, 'base64');
  let sig = crypto.createHmac('sha256', key).update(StringToSign, 'utf8').digest('base64');

  let sas =
    `se=${signedexpiry}
     &sp=${(signedpermissions)}
     &sv=${(signedversion)}
     &ss=${(signedservice)}
     &srt=${(signedresourcetype)}
     &sig=${encodeURIComponent(sig)}`;

  res.json({
      storageUri: STORAGE_ACCOUNT_NAME,
      storageAccessToken: sas
  });
});

当我的客户最终使用生成的 SAS 令牌发出请求时,我收到一个错误:

403 (Server failed to authenticate the request. 
Make sure the value of Authorization header is formed correctly including the signature.)

是否可以为 Node.js 中的 Blob 存储生成 Account SAS 令牌

【问题讨论】:

    标签: javascript node.js azure azure-storage


    【解决方案1】:

    根据我的研究,我们可以使用 Azure 存储 SDK azure-storage。更多详情请参考https://github.com/Azure/azure-storage-node/blob/0557d02cd2116046db1a2d7fc61a74aa28c8b557/test/accountsas-tests.js

    var storage = require("azure-storage")
    var startDate = new Date();
        var expiryDate = new Date();
        startDate.setTime(startDate.getTime() - 5*60*1000);
        expiryDate.setTime(expiryDate.getTime() + 24*60*60*1000);
        var AccountSasConstants = storage.Constants.AccountSasConstants;
        var sharedAccessPolicy = {
          AccessPolicy: {
            Services: AccountSasConstants.Services.BLOB ,
            ResourceTypes: AccountSasConstants.Resources.SERVICE + 
                           AccountSasConstants.Resources.CONTAINER +
                           AccountSasConstants.Resources.OBJECT,
            Permissions: AccountSasConstants.Permissions.READ + 
                         AccountSasConstants.Permissions.ADD +
                         AccountSasConstants.Permissions.CREATE +
                         AccountSasConstants.Permissions.WRITE +
                         AccountSasConstants.Permissions.DELETE +
                         AccountSasConstants.Permissions.LIST,
            Protocols: AccountSasConstants.Protocols.HTTPSORHTTP,
            Start: startDate,
            Expiry: expiryDate
          }
          
        };
        const accountname ="blobstorage0516";
        const key = "";
        var sas =storage.generateAccountSharedAccessSignature(accountname,key,sharedAccessPolicy);
        console.log(sas);
    

    此外,如果您不想使用 SDK 生成 SAS 令牌,请注意,如果我们不使用 StringToSign 中的一个属性,我们不能省略 \n,并且我们在 StringToSign 中提供的属性应该在我们创建 sas 令牌时使用。 例如

    const accountname ="blobstorage0516";
        const key = "";
    
        const start = new Date(new Date().getTime() - (15 * 60 * 1000));
            const end = new Date(new Date().getTime() + (30 * 60 * 1000));
        const signedpermissions = 'rwdlac';
            const signedservice = 'b';
            const signedresourcetype = 'sco';
            const signedexpiry = end.toISOString().substring(0, end.toISOString().lastIndexOf('.')) + 'Z';
            const signedProtocol = 'https';
            const signedversion = '2018-03-28';
    
            const StringToSign =
                accountname + '\n' +
                signedpermissions + '\n' +
                signedservice + '\n' +
                signedresourcetype + '\n' +
                 '\n' +
                signedexpiry + '\n' +
                 '\n' +
                signedProtocol + '\n' +
          signedversion + '\n';
          
        let sig = crypto.createHmac('sha256', Buffer.from(key, 'base64')).update(StringToSign, 'utf8').digest('base64');
      
        let sasToken =
          `sv=${(signedversion)}&ss=${(signedservice)}&srt=${(signedresourcetype)}&sp=${(signedpermissions)}&se=${encodeURIComponent(signedexpiry)}&spr=${(signedProtocol)}&sig=${encodeURIComponent(sig)}`;
        console.log(sasToken)
        var storageBlobEndpoint = "https://"+ accountname +".blob.core.windows.net"
        var container="blobcontainer";
        var blobName="CP4.png";
        var requestURL = storageBlobEndpoint + "/" + container + "/" + blobName +"?"+sasToken
        console.log(requestURL)
    


    更新

    根据我的测试,我们可以使用上述代码创建的 sas 令牌对 Azure blob 存储进行 smoe 操作。例如

    1。列出容器

    Get https://<your account>.blob.core.windows.net/?comp=list+ "&"+"<your sas token>"
    

    2。获取容器属性

    Get https://<your account>.blob.core.windows.net/<your container>?restype=container&comp=list +"&" +"<your sas token>"
    

    另外,关于如何使用新的sdk@azure/storage-blob创建SAS token,请参考以下代码

    const accountname ="blobstorage0516";
        const key = "";
        const signedpermissions = 'rwdlac';
            const signedservice = 'b';
            const signedresourcetype = 'sco';
            
            const signedProtocol = 'https';
            const signedversion = '2018-03-28';
        const cerds = new storage.StorageSharedKeyCredential(accountname,key);
        var startDate = new Date();
        var expiryDate = new Date();
        startDate.setTime(startDate.getTime() - 5*60*1000);
        expiryDate.setTime(expiryDate.getTime() + 24*60*60*1000);
        expiryDate.setTime(expiryDate.getTime() + 24*60*60*1000);
        var result = storage.generateAccountSASQueryParameters({
          expiresOn : expiryDate,
          permissions: storage.AccountSASPermissions.parse(signedpermissions),
          protocol: storage.SASProtocol.Https,
          resourceTypes: storage.AccountSASResourceTypes.parse(signedresourcetype).toString(),
          services: storage.AccountSASServices.parse(signedservice).toString(),
          startsOn: startDate,
          version:signedversion
    
        },cerds).toString();
        console.log(result);
        
    

    【讨论】:

    • 感谢您的详细解答。我想避免使用 azure-storage 模块,因为他们的旧版 SDK 在那里。如果我确实使用 azure 模块,我更喜欢他们较新的模块 @azure/storage-blob。我确实使用您的代码 sn-p 来手动生成 sas 令牌。当我发出请求时,令牌仍然给出相同的 403 错误。此外,您的 requestURL 具有容器和文件名。我想访问容器。
    • @codeherk 我已经更新了我的答案。请检查一下。
    • signedservicesignedresourcetype 是什么意思?可以告诉我应该在我的情况下插入什么吗?
    【解决方案2】:

    尝试使用 @azure/storage-blob npm 包

    const sasString = generateAccountSASQueryParameters({ ... }, sharedKeyCredential).toString()

    请参阅https://azuresdkdocs.blob.core.windows.net/$web/javascript/azure-storage-blob/12.0.0/globals.html#generateaccountsasqueryparameters

    【讨论】:

    • 你能提供一个代码sn-p吗?我研究了 azure-storage (v2 legacy) 和 @azure/storage-blob (v10 new)。我对新模块有点陌生,他们的文档没有提供使用它生成令牌的示例。如果您确实对生成一个没有模块的想法有任何想法,请分享。
    猜你喜欢
    • 2021-10-02
    • 2021-09-02
    • 2020-05-29
    • 2021-11-20
    • 2019-12-05
    • 2021-05-12
    • 2021-11-08
    • 2019-01-14
    • 1970-01-01
    相关资源
    最近更新 更多