Генерация sas токенов хранилища BLOB-объектов Azure с помощью js - PullRequest
0 голосов
/ 30 января 2019

У меня есть эта функция, запущенная в функции Azure, чтобы получить токен sas для приложения браузера, чтобы загрузить в хранилище BLOB-объектов Azure:

var azure = require('azure-storage');

module.exports = function(context, req) {
  if (req.body.container) {
    // The following values can be used for permissions:
    // "a" (Add), "r" (Read), "w" (Write), "d" (Delete), "l" (List)
    // Concatenate multiple permissions, such as "rwa" = Read, Write, Add
    context.res = generateSasToken(
      context,
      req.body.container,
      req.body.blobName,
      req.body.permissions
    );
  } else {
    context.res = {
      status: 400,
      body: "Specify a value for 'container'"
    };
  }

  context.done(null, context);
};

function generateSasToken(context, container, blobName, permissions) {
  var connString = process.env.AzureWebJobsStorage;
  var blobService = azure.createBlobService(connString);

  // Create a SAS token that expires in an hour
  // Set start time to five minutes ago to avoid clock skew.
  var startDate = new Date();
  startDate.setMinutes(startDate.getMinutes() - 5);
  var expiryDate = new Date(startDate);
  expiryDate.setMinutes(startDate.getMinutes() + 60);

  permissions = azure.BlobUtilities.SharedAccessPermissions.READ +
                azure.BlobUtilities.SharedAccessPermissions.WRITE +
                azure.BlobUtilities.SharedAccessPermissions.DELETE +
                azure.BlobUtilities.SharedAccessPermissions.LIST;

  var sharedAccessPolicy = {
    AccessPolicy: {
      Permissions: permissions,
      Start: startDate,
      Expiry: expiryDate
    }
  };

  var sasToken = blobService.generateSharedAccessSignature(
    container,
    blobName,
    sharedAccessPolicy
  );

  context.log(sasToken);

  return {
    token: sasToken,
    uri: blobService.getUrl(container, blobName, sasToken, true)
  };
}

Затем я вызываю этот URL в клиенте и пытаюсьзагрузить с этим кодом:

const search = new URLSearchParams(`?${token}`);

const sig = encodeURIComponent(search.get('sig'));

const qs = `?sv=${search.get('sv')}&ss=b&srt=sco&sp=rwdlac&se=${search.get('sv')}&st=${search.get(
  'st'
)}&spr=https&sig=${sig}`;

return `${url}/${containerName}/${filename}${qs}`;

, который генерирует URL, подобный этому:

https://mystorage.blob.core.windows.net/mycontainer/latest.png?sv=2018-03-28&ss=b&srt=sco&sp=rwdlac&se=2018-03-28&st=2019-01-30T19:11:10Z&spr=https&sig=g0sceq3EkiAQTvyaZ07C+C4SZQz9FaGTV4Zwq4HkAnc=

, который возвращает эту ошибку:

403 (Серверу не удалось аутентифицировать запрос. Убедитесь, что значение заголовка Authorization сформировано правильно, включая подпись.)

Если я сгенерирую токен sas на портале Azure, он будет работать, поэтому сгенерированный URLвыглядит так:

https://mystorage.blob.core.windows.net/mycontainer/latest.png?sv=2018-03-28&ss=b&srt=sco&sp=rwdlac&se=2019-01-31T03:01:43Z&st=2019-01-30T19:01:43Z&spr=https&sig=ayE4gt%2FDfDzjv5DjMaD7AS%2F176Bi4Q6DWJNlnDzl%2FGc%3D

но мой URL выглядит так:

https://mystorage.blob.core.windows.net/mycontainer/latest.png?sv=2018-03-28&ss=b&srt=sco&sp=rwdlac&se=2019-01-31T03:34:21Z&st=2019-01-30T19:34:21Z&spr=https&sig=Dx8Vm4XPnD1rn9uyzIAXZEfcdbWb0HjmOq%2BIq42Q%2FOM%3D

Я понятия не имею, что нужно сделать, чтобы это заработало

Ответы [ 3 ]

0 голосов
/ 31 января 2019

Проблема в том, что в своем коде на стороне сервера вы создаете Service SAS, а затем берете только часть подписи кода (sig) и создаете Account SAS на клиенте.

Поскольку параметры, использованные для создания токена, теперь изменились (в исходном случае у вас не было таких параметров, как ss, srt и т. Д., Но при создании собственного URL-адреса вы 'вставьте эти параметры), при использовании измененного URL-адреса SAS вы получите ошибку 403.Это происходит потому, что сервер снова вычисляет подпись на основе параметров URL и сравнивает ее с подписью, переданной в URL.Поскольку две подписи не совпадают, вы получаете ошибку 403.

Поскольку вы возвращаете SAS-URL-адрес большого двоичного объекта, вам не нужно создавать URL-адрес на клиенте.Вы можете просто использовать uri, который вы возвращаете со своего уровня API на клиенте, и использовать его для загрузки.

0 голосов
/ 09 июля 2019

Как объяснил ответ Джерри Лю, ваша функция Azure генерирует правильный токен и уже дает вам правильный uri для использования, который включает в себя имя и токен большого двоичного объекта.

На стороне клиента вы также можете использовать Azure-SDK-для-JS

// This is the response from your api with token and uri    
const uri = response.uri;

const pipeline = StorageURL.newPipeline(new AnonymousCredential());

// Your uri already includes the full blob url with SAS signature
const blockBlobURL = BlockBlobURL.fromBlobURL(new BlobURL(uri, pipeline));
const uploadBlobResponse = await blockBlobURL.upload(
  Aborter.none,
  file,
  file.size,
  { blobHTTPHeaders: { blobContentType: `${mime}; charset=utf-8`} }
);
0 голосов
/ 31 января 2019

Ваш код функции Azure правильный, а

var sasToken = blobService.generateSharedAccessSignature(
    container,
    blobName,
    sharedAccessPolicy
);

- это именно тот sasToken, который вам нужен для загрузки BLOB-объекта.Не нужно снова обрабатывать токен (на самом деле неправильно), как вы делали во втором фрагменте кода.

Ожидается, что токен sas на портале Azure (учетная запись SAS) отличается от токена, сгенерированного в вашем коде (служба SAS).Взгляните на doc .

В заключение,

  1. Убедитесь, что строка подключения принадлежит к хранилищу, к которому вы хотите подключиться.Вы можете избежать проблем и напрямую заменить var connString = process.env.AzureWebJobsStorage; на var connString = "connectionStringGotFromPortal";

  2. Если подтверждено значение 1, код функции Azure верен и возвращает ожидаемый токен

    {
      token: sasToken,
      uri: blobService.getUrl(container, blobName, sasToken, true)
    };  
    
  3. На основании предоставленного вами второго фрагмента кода

    return `${url}/${containerName}/${filename}?${token}`; 
    

    требуется только в том случае, если токен совпадает с возвращаемым функцией.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...