如何为Azure存储生成帐户SAS令牌?

时间:2019-11-12 21:48:27

标签: javascript node.js azure azure-storage

理想情况下,我想访问存储中的所有容器和Blob。 我的代码在服务器端生成了帐户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令牌

2 个答案:

答案 0 :(得分: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令牌,请注意,如果我们不使用\n中的一个属性以及我们在其中提供的属性,则不能省略StringToSign创建sas令牌时,应使用StringToSign。 例如

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)

enter image description here enter image description here


更新

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

1。列出容器

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

enter image description here enter image description here

2。获取容器属性

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

enter image description here 此外,关于如何使用新的SDK @azure/storage-blob创建SAS令牌,请参考以下代码

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);

答案 1 :(得分:0)

尝试使用@ 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