Авторизация в Azure Data Lake Gen2

#javascript #node.js #azure-data-lake-gen2

#javascript #node.js #azure-data-lake-gen2

Вопрос:

Я пытаюсь создать подпись общего доступа на стороне клиента в моем приложении узла. Причина в том, что я не хочу передавать файлы через свое приложение. Я хочу, чтобы пользователь мог напрямую загружать файл в мой контейнер для хранения больших двоичных объектов Azure Data Lake Gen2.

Я просмотрел все примеры, которые смог найти, но все они на стороне сервера. Итак, я попытался сгенерировать параметры generateDataLakeSASQueryParameters и использовать их в запросе ВВОДА. Процесс выглядит так, как будто он работает, и я возвращаю его клиенту.

На стороне сервера:

 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 со следующей ошибкой:

Подпись MAC, найденная в HTTP-запросе ‘[signature]’, не совпадает с любой вычисленной подписью. Сервер использовал следующую строку для подписи: ‘PUT n n n n1762213n n n n n n n n n n n nx-ms-дата:Чт, 24 Сен 2020 12:24:05 GMT nx-ms-версия:2019-12-12n/[имя учетной записи]/ [имя контейнера]/ [имя папки]/image.png’.

Очевидно, я удалил фактическую подпись, поскольку я заставил ее работать на стороне сервера, но она выглядит примерно так: hGhg765 nigjhgluhuuuyg686dnh90hkyfytf6= (Я это придумал, но похоже, что она в правильном формате).

Я также пытался вернуть проанализированную строку запроса и использовать ее в запросе PUT, но затем я получаю ошибки, указывающие, что отсутствует требуемый заголовок, и я не могу понять, какой из них должен быть. Authorization Например, не требуется.

Ответ №1:

Этот метод generateDataLakeSASQueryParameters используется для создания токена службы sas. После этого мы можем вызвать Azure Datalake Rest API с токеном sas в качестве параметра запроса

Например

  1. Создайте токен sas с помощью метода generateDataLakeSASQueryParameters . Когда мы вызываем метод generateDataLakeSASQueryParameters , мы должны определить DataLakeSASSignatureValues класс: https://learn.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. Тест (создать файл)
 PUT http:// https://{accountName}.{dnsSuffix}/{filesystem}/{path}
?{sas token you create in step1}

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

  

введите описание изображения здесь

Комментарии:

1. Внес предложенные изменения, все равно получите это в ответе: MissingRequiredHeader: An HTTP header that's mandatory for this request is not specified.

2. @Vhendin Пожалуйста, обратитесь к learn.microsoft.com/en-us/rest/api/storageservices /… чтобы определить ваш api.

3. @JimXu, спасибо!! Я потратил часы, просматривая документы, пытаясь разобраться в этом. Для меня все работало отлично