Подпись общего доступа не работает в файлах Azure с подпапками - PullRequest
0 голосов
/ 15 февраля 2019

(Обновлено ниже с ответом) У меня была рабочая программа, которая хранит PDF-файлы в общей папке отчетов Azure Files ([domain] .file.core.windows.net / reports).После сохранения файла я немедленно получаю подпись Shared Access для этого файла, объединяю его с физическим именем файла и сохраняю результат в записи транзакции отчета.

//create the storage location if it doesn't exist
var shareRoot = _blob.CreateCloudFileClient().GetShareReference("reports").GetRootDirectoryReference();

//get reference to azure file and copy the PDF report stream to it
CloudFile cloudFile = GetCloudFile("reports", storedFileName);
using (CloudFileStream strm = await cloudFile.OpenWriteAsync(stream.Length))
{ 
    await stream.CopyToAsync(strm); 
}

//get SAS using stored policy and create stored file name
string token = cloudFile.GetSharedAccessSignature(null, "myPolicy");
token = new Uri(cloudFile.StorageUri.PrimaryUri.ToString() + token).ToString();

// function to centralize calls for files  
private CloudFile GetCloudFile(string fileShare, string fileName)
{
    // Parse the connection string and get a reference to storage file
    //See UPDATE below: ***THIS WAS THE PROBLEM*****
    return _blob.CreateCloudFileClient().GetShareReference(fileShare).GetRootDirectoryReference().GetFileReference(fileName);
}

Пример строки доступа к сохраненному файлу из старого кода: https://[domain].file.core.windows.net/reports/[filename].pdf?sv=2018-03-28&sr=f&si=myPolicy&sig=Wd1BkHPRTPHDiezA%2FWe4CD4mOJIyILxDUXxrxjH1byU%3D

В любое время я могу вставить этот URL в браузер и вызвать PDF.

Все работало хорошо, пока в каталоге «отчетов» не было слишком много отчетов для прокрутки, поэтому я изменил программу для создания подпапок в каталоге «отчеты» на основе месяца (например, «201902»),Физическое местоположение файла теперь [домен] .file.core.windows.net / reports / 201902.Я изменил код, добавив подпапку и сохранив в ней файл:

//create the storage location if it doesn't exist -- same as before
var shareRoot = _blob.CreateCloudFileClient().GetShareReference("reports").GetRootDirectoryReference();
//create new subfolder if needed
await shareRoot.GetDirectoryReference("201902").CreateIfNotExistsAsync();

//get reference to azure file in subfolder and copy the PDF report stream to it
CloudFile cloudFile = GetCloudFile("reports/201902", storedFileName);

С этого момента строка токена больше не может обращаться к PDF.

Пример сохраненного файластрока доступа из нового кода: https://[domain].file.core.windows.net/reports/201902/[filename].pdf?sv=2018-03-28&sr=f&si=myPolicy&sig=YZ64hSk5IKQOs%2BhgACfBlQk%2F6r8OqiA7D8DBv%2F3G%2FyA%3D

Когда я вставляю эту строку в адресную строку, возвращается

<?xml version="1.0" encoding="ISO-8859-1"?>
<Error>
    <Code>AuthenticationFailed</Code>
    <Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. RequestId:e51d0e3c-e01a-003e-27bf-c49bf8000000 Time:2019-02-14T23:46:20.4325820Z</Message>
    <AuthenticationErrorDetail>Signature did not match. String to sign used was /file/[domain]/reports/201902/[filename].pdf myPolicy 2018-03-28 </AuthenticationErrorDetail>
</Error>

Никаких других изменений не было сделано - ключ доступа являетсяи т. д. Если я перехожу к файлу на портале Azure, он действительно сохраняется в reports / 201902 с указанным мною именем файла.Я могу загрузить его с портала без проблем (но портал генерирует свой собственный токен SAS, так что это не помогает).

Думая, что это может иметь отношение к хранимой политике (myPolicy), я сгенерировалновый и пробовал, но ничего не изменилось.Политика хранится в корне общего ресурса (отчеты), а не в подпапке (reports / 201902), потому что нет способа указать политику на уровне подпапок.

Если у кого-либо есть какие-либо предложения, я был бы признателен,

1 Ответ

0 голосов
/ 16 февраля 2019

ОБНОВЛЕНИЕ С ОТВЕТОМ

Как правильно предположил Гаурав Мантри, проблема была в методе GetCloudFile, где я даже не смотрел.При создании файла он получал ссылку на корневой каталог «отчеты» вместо подпапки «201902».Путем явного указания «reports / 201902» в имени файла, которое нужно сохранить, Azure помещал файл в нужное место, но SAS записывался для корневого общего ресурса «reports», а не для подпапки «201902».Таким образом, никогда не будет никакого способа вызвать файл, потому что физический URI был правильным, но безопасность никогда не будет соответствовать.

Новый код показан ниже.Спасибо Гаураву за правильный вопрос.

Новый код, который работает:

//UPDATED: moved folder creation to GetCloudFile method

//UPDATED: get reference to azure file and copy the PDF report stream to it
CloudFile cloudFile = await GetCloudFile(REPORT_SHARE, fPath, storedFileName);
using (CloudFileStream strm = await cloudFile.OpenWriteAsync(stream.Length))
{ 
    await stream.CopyToAsync(strm); 
}

//get SAS using stored policy and create stored file name
string token = cloudFile.GetSharedAccessSignature(null, "myPolicy");
token = new Uri(cloudFile.StorageUri.PrimaryUri.ToString() + token).ToString();

// UPDATED: method to get the cloud file to store uploads and reports  
private async Task<CloudFile> GetCloudFile(string shareRoot, string shareFolder, string fileName)
{
    //create the subpath if it doesn't exist
    var sRoot = _blob.CreateCloudFileClient().GetShareReference(shareRoot).GetRootDirectoryReference();
    await sRoot.GetDirectoryReference(shareFolder).CreateIfNotExistsAsync();

    //create and return the file reference
    return sRoot.GetDirectoryReference(shareFolder).GetFileReference(fileName);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...