Azure数据湖Gen2 PUT授权

时间:2020-09-24 14:13:54

标签: javascript node.js azure-data-lake-gen2

我正在尝试在Node应用程序中创建一个共享访问签名客户端。原因是我不想通过应用程序流式传输文件。我希望用户能够直接将文件上传到我的Azure Data Lake Gen2 Blob存储容器。

我看了所有可以找到的示例,但是它们都是服务器端的。因此,我尝试生成generateDataLakeSASQueryParameters并将其用于PUT请求中。该过程看起来可行,我将其返回给客户端。

服务器端:

async getFileUploadUrl(path) {
    const now = new Date().toUTCString();
    const startsOn = new Date(now);
    startsOn.setMinutes(startsOn.getMinutes() - 10); // Skip clock skew with server
    
    const expiresOn = new Date(now);
    expiresOn.setHours(expiresOn.getHours() + 1); // Expires in one hour

    const sharedKeyCredential = new StorageSharedKeyCredential(this.storageAccountName, this.accountKey);

    const sas = generateDataLakeSASQueryParameters({
        fileSystemName: this.fileSystemClient.name,
        ipRange: { start: "0.0.0.0", end: "255.255.255.255" },
        expiresOn,
        protocol: SASProtocol.HttpsAndHttp,
        permissions: DataLakeSASPermissions.parse("c").toString(), //  Read (r), Write (w), Delete (d), List (l), Add (a), Create (c), Update (u), Process (p)
        resourceTypes: AccountSASResourceTypes.parse("o").toString(), //  Service (s), Container (c), Object (o)
        services: AccountSASServices.parse("b").toString(), //  Blob (b), Table (t), Queue (q), File (f)
        startsOn,
        version: "2019-12-12"
    },
    sharedKeyCredential);
    


    const encodedURI = encodeURI(path);


    const filePath = `${this.fileSystemClient.url}/${encodedURI}`; 

    return {
        url: filePath,
        signature: sas.signature,
    };
}

客户端:

const { url, signature } = serverResponse;

const file = [file takes from an input tag];

const request = new XMLHttpRequest();
request.open('PUT', url, true);
request.setRequestHeader("x-ms-date", new Date().toUTCString());
request.setRequestHeader("x-ms-version", '2019-12-12');
request.setRequestHeader("x-ms-blob-type", 'BlockBlob');
request.setRequestHeader("Authorization", `SharedKey [storageaccount]:${signature}`);

request.send(file);

我一直回想的是403,出现以下错误:

在HTTP请求“ [signature]”中找到的MAC签名不是 与任何计算出的签名相同。服务器使用以下字符串进行签名: 'PUT \ n \ n \ n1762213 \ n \ nimage / png \ n \ n \ n \ n \ n \ n \ nx-ms-date:2020年9月24日,星期四 12:24:05 GMT \ nx-ms-version:2019-12-12 \ n / [帐户名称] / [容器 名称] / [文件夹名称] /image.png'。

很显然,我已经删除了实际的签名,因为我已经将其用于服务器端,但是它看起来像这样:hGhg765 + NIGjhgluhuUYG686dnH90HKYFytf6 =(我做了这个,但看起来好像是正确的格式)。

我也尝试返回解析的查询字符串并在PUT请求中使用,但是随后出现错误,指出缺少所需的标头,并且我无法确定应该是哪个标头。例如,无需Authorization

1 个答案:

答案 0 :(得分:0)

方法generateDataLakeSASQueryParameters用于创建service sas token。之后,我们可以使用sas令牌作为查询参数调用Azure Datalake Rest API

例如

  1. 使用方法generateDataLakeSASQueryParameters创建一个sas令牌。当我们调用方法generateDataLakeSASQueryParameters时,我们应该定义一个DataLakeSASSignatureValues 类:https://docs.microsoft.com/en-us/javascript/api/@azure/storage-file-datalake/datalakesassignaturevalues?view=azure-node-latest
const {
  StorageSharedKeyCredential,
  generateDataLakeSASQueryParameters,
  DataLakeSASPermissions,
} = require("@azure/storage-file-datalake");

const accountName = "testadls05";
const accountKey ="";
const now = new Date().toUTCString();
const startsOn = new Date(now);
startsOn.setMinutes(startsOn.getMinutes() - 10); // Skip clock skew with server

const expiresOn = new Date(now);
expiresOn.setHours(expiresOn.getHours() + 1); // Expires in one hour

const fileSas = generateDataLakeSASQueryParameters(
  {
    fileSystemName: "test",
    pathName: "test.jpg",
    permissions: DataLakeSASPermissions.parse("racwd"),
    startsOn: startsOn,
    expiresOn: expiresOn,
  },
  new StorageSharedKeyCredential(accountName, accountKey)
).toString();
console.log(fileSas);
  1. 测试(create file
PUT http:// https://{accountName}.{dnsSuffix}/{filesystem}/{path}
?{sas token you create in step1}

Headers:
  Content-Type:image/jpeg
  Content-Length:0

enter image description here