如何为同一Azure blob容器创建多个存储的访问策略?

时间:2015-06-08 20:07:48

标签: azure blob azure-storage-blobs policy

我已阅读并使用https://azure.microsoft.com/en-us/documentation/articles/storage-dotnet-shared-access-signature-part-2/#part-1-create-a-console-application-to-generate-shared-access-signatures

中的示例代码

然后我将它应用到我的场景中。

我编写了一个工具,用于将数据从合作伙伴上传到Azure blob存储,然后由一些内部团队使用: YYYY-MM(容器)                 (DD-GUID)(前缀)                                 File1.zip                                 File2.zip ......

我为每个容器创建了2个策略: 1.只为合作伙伴写,这样他们只能写blob而不能写任何其他内容。 2.列出并阅读我们的内部团队,以便他们可以列出并阅读(下载)容器中的所有blob。

我的想法是,我可以简单地将正确的政策交给正确的收件人;但是,我的实现并不像我预期的那样有效。

我使用以下方法为每个容器创建了2个策略,当然每个策略都有正确的权限:

static void CreateSharedAccessPolicy(CloudBlobClient blobClient, CloudBlobContainer container, string policyName)
    {
        //Create a new stored access policy and define its constraints.
        SharedAccessBlobPolicy sharedPolicy = new SharedAccessBlobPolicy()
        {
            SharedAccessExpiryTime = DateTime.UtcNow.AddHours(10),
            Permissions = SharedAccessBlobPermissions.Read | SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.List
        };

        //Get the container's existing permissions.
        BlobContainerPermissions permissions = new BlobContainerPermissions();

        //Add the new policy to the container's permissions.
        permissions.SharedAccessPolicies.Clear();
        permissions.SharedAccessPolicies.Add(policyName, sharedPolicy);
        container.SetPermissions(permissions);
    }

我首先创建了只写策略,然后创建了读取和列表策略。我观察到的是第一个策略似乎不起作用,一切都得到了403 Forbidden,对于第二个策略,唯一有效的是List blob但不是Read(我试图下载blob但得到了404没找到。)

好像我错过了一些非常基本的东西。你能帮助我看看我的方法有什么问题吗?

我用来测试容器权限的代码,我还注意到容器上的读取权限并不像Azure文档中提到的那样真正起作用。在这里,我试图找到一种简单的方法来简单地为人们提供存储的访问策略,以便他们可以列出并下载容器中的所有blob,而不是为每个blob文件提供签名:

static void UseContainerSAS(string sas)         {             //尝试使用提供的SAS执行容器操作。

        //Return a reference to the container using the SAS URI.
        CloudBlobContainer container = new CloudBlobContainer(new Uri(sas));

        //Create a list to store blob URIs returned by a listing operation on the container.
        List<Uri> blobUris = new List<Uri>();

        try
        {
            //Write operation: write a new blob to the container. 
            CloudBlockBlob blob = container.GetBlockBlobReference("blobCreatedViaSAS.txt");
            string blobContent = "This blob was created with a shared access signature granting write permissions to the container. ";
            MemoryStream msWrite = new MemoryStream(Encoding.UTF8.GetBytes(blobContent));
            msWrite.Position = 0;
            using (msWrite)
            {
                blob.UploadFromStream(msWrite);
            }
            Console.WriteLine("Write operation succeeded for SAS " + sas);
            Console.WriteLine();
        }
        catch (StorageException e)
        {
            Console.WriteLine("Write operation failed for SAS " + sas);
            Console.WriteLine("Additional error information: " + e.Message);
            Console.WriteLine();
        }

        try
        {
            //List operation: List the blobs in the container, including the one just added.
            foreach (ICloudBlob blobListing in container.ListBlobs())
            {
                blobUris.Add(blobListing.Uri);
            }
            Console.WriteLine("List operation succeeded for SAS " + sas);
            Console.WriteLine();
        }
        catch (StorageException e)
        {
            Console.WriteLine("List operation failed for SAS " + sas);
            Console.WriteLine("Additional error information: " + e.Message);
            Console.WriteLine();
        }

        try
        {
            CloudBlockBlob blob = container.GetBlockBlobReference(blobUris[0].ToString());

            MemoryStream msRead = new MemoryStream();
            msRead.Position = 0;
            using (msRead)
            {
                blob.DownloadToStream(msRead);
                Console.WriteLine(msRead.Length);
            }
            Console.WriteLine("Read operation succeeded for SAS " + sas);
            Console.WriteLine();
        }
        catch (StorageException e)
        {
            Console.WriteLine("Read operation failed for SAS " + sas);
            Console.WriteLine("Additional error information: " + e.Message);
            Console.WriteLine();
        }
        Console.WriteLine();

        try
        {
            //Delete operation: Delete a blob in the container.
            CloudBlockBlob blob = container.GetBlockBlobReference(blobUris[0].ToString());
            blob.Delete();
            Console.WriteLine("Delete operation succeeded for SAS " + sas);
            Console.WriteLine();
        }
        catch (StorageException e)
        {
            Console.WriteLine("Delete operation failed for SAS " + sas);
            Console.WriteLine("Additional error information: " + e.Message);
            Console.WriteLine();
        }
    }

1 个答案:

答案 0 :(得分:7)

实际上,后一种操作会删除您在第一次操作中所做的操作。为避免这种情况,您应该阅读容器的现有权限,添加新权限,然后将权限设置回容器。

以下是正确的代码示例:

static void CreateSharedAccessPolicy(CloudBlobClient blobClient, CloudBlobContainer container, string policyName)
{
    //Create a new stored access policy and define its constraints.
    SharedAccessBlobPolicy sharedPolicy = new SharedAccessBlobPolicy()
    {
        SharedAccessExpiryTime = DateTime.UtcNow.AddHours(10),
        Permissions = SharedAccessBlobPermissions.Read | SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.List
    };

    //Get the container's existing permissions.
    BlobContainerPermissions permissions = container.GetPermissions();

    //Add the new policy to the container's permissions.
    permissions.SharedAccessPolicies.Add(policyName, sharedPolicy);
    container.SetPermissions(permissions);
}

由于您在阅读blob时遇到404错误的原因,请分享您按策略创建SAS的代码以及如何使用创建的SAS读取blob以便我可以帮助解决问题。

以下是用于创建SAS并使用它来读取blob的代码示例:(您可以直接将stdout中的URL复制并粘贴到浏览器中进行试用)

        var permissions = container.GetPermissions();
        var policy = new SharedAccessBlobPolicy
        {
            Permissions = SharedAccessBlobPermissions.Read,
            SharedAccessExpiryTime = DateTime.UtcNow.AddYears(1),
        };

        string policyName = "read";
        permissions.SharedAccessPolicies.Add(policyName, policy);
        container.SetPermissions(permissions);
        string sas = container.GetSharedAccessSignature(null, policyName);
        var blobs = container.ListBlobs(null, true);
        Console.WriteLine("SAS = {0}", sas);
        Console.WriteLine("Blobs URLs with SAS:");

        foreach (var blob in blobs)
        {
            Console.WriteLine(blob.Uri.ToString() + sas);
        }