繁体   English   中英

共享访问签名在带有子文件夹的Azure文件中不起作用

[英]Shared Access Signature not working in Azure Files with subfolders

(下面用答案更新)我有一个工作程序,将PDF存储在Azure文件“报告”共享([domain] .file.core.windows.net / reports)中。 存储文件后,我立即获得该文件的共享访问签名,将其连接到物理文件名上,并将结果存储在报告事务记录中。

//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”)在“报告”目录中创建子文件夹。 物理文件位置现在为[domain] .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 Portal中导航到该文件,则该文件确实以我指定的文件名存储在report / 201902中。 我可以毫无问题地从门户网站下载它(但是门户网站会生成自己的SAS令牌,因此无济于事)。

考虑到它可能与存储策略(myPolicy)有关,我生成了一个新策略并进行了尝试,但没有任何变化。 该策略存储在共享根目录(报告)而非子文件夹(reports / 201902)中,因为无法在子文件夹级别指定策略。

如果有人有任何建议,我将不胜感激。

用答案更新

正如Gaurav Mantri正确推测的那样,问题出在我甚至没有看过的GetCloudFile方法中。 创建文件时,它得到的是对根目录“ reports”的引用,而不是对子文件夹“ 201902”的引用。 通过在要存储的文件名中明确指定“ reports / 201902”,Azure将文件放置在正确的位置,但是SAS是针对根“ reports”共享而不是针对“ 201902”子文件夹编写的。 因此,由于物理URI正确,但是安全性永远不会匹配,因此永远不会有任何方法来调用该文件。

新代码如下所示。 感谢Gaurav提出正确的问题。

有效的新代码:

//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);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM