javascript - 如何为Azure存储生成帐户SAS token ?

标签 javascript node.js azure azure-storage

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

遵循 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" 

文档中的示例 token (为了更好的可见性分成多行):

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 生成的 token :

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

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

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

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 token 发出请求时,我收到一条错误:

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

是否可以为 Node.js 中的 Blob 存储生成帐户 SAS token

最佳答案

根据我的研究,我们可以使用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 token ,请注意,如果我们不使用 StringToSign 中的一个属性,我们就不能省略 \n > 当我们创建 sas token 时,应该使用我们在 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 token 在 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 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);
    

关于javascript - 如何为Azure存储生成帐户SAS token ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58827196/

相关文章:

刷新 token 未签署 JWT 后收到的 Azure AD Adal4j token

azure - 如何通过 Azure 门户查找虚拟机上的 Windows 版本

javascript - Bootstrap 模式奇怪的问题

javascript - 如何在需要转换为 JS Obj 的 JSON 字符串中传递 "this"

javascript - 错误 : No version of chokidar is available. 已尝试 chokidar@2 和 chokidar@3。将 npm 升级到 7.*.* 后

node.js - 如何在 ReactJs 组件中调用 oidc-client signinSilentCallback

javascript - 使用 AJAX 和 PHP 重新加载 TINYMCE 3.5

node.js - Loopback 4不会生成构建文件

python - 在不保存的情况下获取 PIL 图像的二进制表示

azure iot hub如何作为服务器订阅设备孪生更改