【问题标题】:Azure Data Lake Gen2 PUT authorizationAzure Data Lake Gen2 PUT 授权
【发布时间】:2020-09-25 16:17:52
【问题描述】:

我正在尝试在我的 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 请求“[签名]”中找到的 MAC 签名不是 与任何计算的签名相同。服务器使用以下字符串进行签名: 'PUT\n\n\n1762213\n\nimage/png\n\n\n\n\n\n\nx-ms-date:Thu, 2020 年 9 月 24 日 格林威治标准时间 12:24:05\nx-ms-version:2019-12-12\n/[账户名]/[容器 名称]/[文件夹名称]/image.png'。

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

我还尝试返回解析后的查询字符串并在 PUT 请求中使用,但随后我收到错误消息,指出缺少必需的标头,我无法确定应该是哪个标头。例如,不需要Authorization

【问题讨论】:

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


    【解决方案1】:

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

    例如

    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
    
    

    【讨论】:

    • 进行了建议的更改,但仍然在响应中得到这个:MissingRequiredHeader: An HTTP header that's mandatory for this request is not specified.
    • @Vhendin 请参考docs.microsoft.com/en-us/rest/api/storageservices/… 来定义你的api。
    • @JimXu,谢谢!!我花了几个小时浏览文档试图弄清楚这一点。非常适合我
    猜你喜欢
    • 2020-06-14
    • 2019-12-02
    • 1970-01-01
    • 2019-09-10
    • 2020-09-22
    • 2023-04-02
    • 2021-03-06
    • 1970-01-01
    • 2020-01-13
    相关资源
    最近更新 更多