共享访问签名,第 2 部分:创建 SAS 并将其用于 Blob 存储Shared Access Signatures, Part 2: Create and use a SAS with Blob storage

本教程的第 1 部分介绍了共享访问签名 (SAS) 并说明了使用共享访问签名的最佳做法。Part 1 of this tutorial explored shared access signatures (SAS) and explained best practices for using them. 第 2 部分演示如何生成共享访问签名以及如何将共享访问签名用于 Blob 存储。Part 2 shows you how to generate and then use shared access signatures with Blob storage. 示例是用 C# 编写的并使用了 Azure .NET 存储客户端库。The examples are written in C# and use the Azure Storage Client Library for .NET. 本教程中的示例:The examples in this tutorial:

  • 在容器上生成共享访问签名Generate a shared access signature on a container
  • 在 Blob 上生成共享访问签名Generate a shared access signature on a blob
  • 创建用于管理容器资源上的签名的存储访问策略Create a stored access policy to manage signatures on a container's resources
  • 在客户端应用程序中测试共享访问签名Test the shared access signatures in a client application

关于本教程About this tutorial

本教程中将创建两个控制台应用程序,用于演示如何创建共享访问签名并将其用于容器和 Blob:In this tutorial, we create two console applications that demonstrate creating and using shared access signatures for containers and blobs:

应用程序 1:管理应用程序。Application 1: The management application. 为容器和 Blob 生成共享访问签名。Generates a shared access signature for a container and a blob. 在源代码中含入存储帐户访问密钥。Includes the storage account access key in source code.

应用程序 2:客户端应用程序。Application 2: The client application. 使用第一个应用程序创建的共享访问签名访问容器和 Blob 资源。Accesses container and blob resources using the shared access signatures created with the first application. 仅使用共享访问签名访问容器和 Blob 资源--它不包括存储帐户访问密钥。Uses only the shared access signatures to access container and blob resources--it does not include the storage account access key.

第 1 部分:创建控制台应用程序以便生成共享访问签名Part 1: Create a console application to generate shared access signatures

首先,确保安装了 Azure .NET 存储客户端库。First, ensure that you have the Azure Storage Client Library for .NET installed. 可以安装包含该客户端库最新程序集的 NuGet 包You can install the NuGet package containing the most up-to-date assemblies for the client library. 这是确保具有最新修补程序的建议方法。This is the recommended method for ensuring that you have the most recent fixes. 还可以通过下载包含该客户端库的最新 Azure SDK for .NET版本来下载该客户端库。You can also download the client library as part of the most recent version of the Azure SDK for .NET.

在 Visual Studio 中,创建一个新的 Windows 控制台应用程序并将其命名为 GenerateSharedAccessSignaturesIn Visual Studio, create a new Windows console application and name it GenerateSharedAccessSignatures. 使用以下方法之一添加对 Microsoft.WindowsAzure.ConfigurationManagerWindowsAzure.Storage 的引用:Add references to Microsoft.WindowsAzure.ConfigurationManager and WindowsAzure.Storage by using one of the following approaches:

  • 使用 Visual Studio 中的 NuGet 包管理器Use the NuGet package manager in Visual Studio. 选择“项目” > “管理 NuGet 包”,联机搜索每个包 (Microsoft.WindowsAzure.ConfigurationManager 和 WindowsAzure.Storage)并进行安装。Select Project > Manage NuGet Packages, search online for each package (Microsoft.WindowsAzure.ConfigurationManager and WindowsAzure.Storage) and install them.
  • 另外,还可以在安装的 Azure SDK 中找到这些程序集,并添加对它们的引用:Alternatively, locate these assemblies in your installation of the Azure SDK and add references to them:
    • Microsoft.WindowsAzure.Configuration.dllMicrosoft.WindowsAzure.Configuration.dll
    • Microsoft.WindowsAzure.Storage.dllMicrosoft.WindowsAzure.Storage.dll

在 Program.cs 文件的顶部,添加以下 using 指令:At the top of the Program.cs file, add the following using directives:

using System.IO;
using Microsoft.Azure;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;

编辑 app.config 文件,使其所含配置设置中的连接字符串指向存储帐户。Edit the app.config file so that it contains a configuration setting with a connection string that points to your storage account. app.config 文件应如下所示:Your app.config file should look similar to this one:

<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
  </startup>
  <appSettings>
    <add key="StorageConnectionString" value="DefaultEndpointsProtocol=https;AccountName=myaccount;AccountKey=mykey;EndpointSuffix=core.chinacloudapi.cn"/>
  </appSettings>
</configuration>

为容器生成共享访问签名 URIGenerate a shared access signature URI for a container

首先添加一个方法,用于在新容器上生成共享访问签名。To begin with, we add a method to generate a shared access signature on a new container. 在此用例中,该签名不与存储访问策略相关联,它在 URI 上携带信息,指示它的到期时间以及授予的权限。In this case, the signature is not associated with a stored access policy, so it carries on the URI the information indicating its expiry time and the permissions it grants.

首先,向 Main() 方法添加代码,以便授权对存储帐户的访问并创建新容器:First, add code to the Main() method to authorize access to your storage account and create a new container:

static void Main(string[] args)
{
    //Parse the connection string and return a reference to the storage account.
    CloudStorageAccount storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));

    //Create the blob client object.
    CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

    //Get a reference to a container to use for the sample code, and create it if it does not exist.
    CloudBlobContainer container = blobClient.GetContainerReference("sascontainer");
    container.CreateIfNotExists();

    //Insert calls to the methods created below here...

    //Require user input before closing the console window.
    Console.ReadLine();
}

接下来,添加一个方法,该方法为容器生成共享访问签名并且返回签名 URI:Next, add a method that generates the shared access signature for the container and returns the signature URI:

static string GetContainerSasUri(CloudBlobContainer container)
{
    //Set the expiry time and permissions for the container.
    //In this case no start time is specified, so the shared access signature becomes valid immediately.
    SharedAccessBlobPolicy sasConstraints = new SharedAccessBlobPolicy();
    sasConstraints.SharedAccessExpiryTime = DateTimeOffset.UtcNow.AddHours(24);
    sasConstraints.Permissions = SharedAccessBlobPermissions.List | SharedAccessBlobPermissions.Write;

    //Generate the shared access signature on the container, setting the constraints directly on the signature.
    string sasContainerToken = container.GetSharedAccessSignature(sasConstraints);

    //Return the URI string for the container, including the SAS token.
    return container.Uri + sasContainerToken;
}

在 Main() 方法的底部,调用 Console.ReadLine() 之前,添加以下代码行,以调用 GetContainerSasUri() 并将签名 URI 写入控制台窗口:Add the following lines at the bottom of the Main() method, before the call to Console.ReadLine(), to call GetContainerSasUri() and write the signature URI to the console window:

//Generate a SAS URI for the container, without a stored access policy.
Console.WriteLine("Container SAS URI: " + GetContainerSasUri(container));
Console.WriteLine();

编译并且运行以输出新容器的共享访问签名 URI。Compile and run to output the shared access signature URI for the new container. 该 URI 与以下类似:The URI will be similar to the following:

https://storageaccount.blob.core.chinacloudapi.cn/sascontainer?sv=2012-02-12&se=2013-04-13T00%3A12%3A08Z&sr=c&sp=wl&sig=t%2BbzU9%2B7ry4okULN9S0wst%2F8MCUhTjrHyV9rDNLSe8g%3D

运行代码后,为容器创建的共享访问签名会在接下来的 24 小时内有效。Once you have run the code, the shared access signature you created for the container will be valid for the next 24 hours. 该签名向客户端授予列出容器中的 Blob 以及将新 Blob 写入容器的权限。The signature grants a client permission to list blobs in the container and to write new blobs to the container.

为 Blob 生成共享访问签名 URIGenerate a shared access signature URI for a blob

接下来编写类似的代码,用于在容器内创建新 Blob 并为其生成共享访问签名。Next, we write similar code to create a new blob within the container and generate a shared access signature for it. 该共享访问签名不与某一存储访问策略相关联,因此,它在 URI 中包括开始时间、到期时间和权限的信息。This shared access signature is not associated with a stored access policy, so it includes the start time, expiry time, and permission information in the URI.

添加一个新方法,该方法创建一个新 Blob 并且向其中写入某些文本,并生成共享访问签名并返回签名 URI:Add a new method that creates a new blob and writes some text to it, then generates a shared access signature and returns the signature URI:

static string GetBlobSasUri(CloudBlobContainer container)
{
    //Get a reference to a blob within the container.
    CloudBlockBlob blob = container.GetBlockBlobReference("sasblob.txt");

    //Upload text to the blob. If the blob does not yet exist, it will be created.
    //If the blob does exist, its existing content will be overwritten.
    string blobContent = "This blob will be accessible to clients via a shared access signature (SAS).";
    blob.UploadText(blobContent);

    //Set the expiry time and permissions for the blob.
    //In this case, the start time is specified as a few minutes in the past, to mitigate clock skew.
    //The shared access signature will be valid immediately.
    SharedAccessBlobPolicy sasConstraints = new SharedAccessBlobPolicy();
    sasConstraints.SharedAccessStartTime = DateTimeOffset.UtcNow.AddMinutes(-5);
    sasConstraints.SharedAccessExpiryTime = DateTimeOffset.UtcNow.AddHours(24);
    sasConstraints.Permissions = SharedAccessBlobPermissions.Read | SharedAccessBlobPermissions.Write;

    //Generate the shared access signature on the blob, setting the constraints directly on the signature.
    string sasBlobToken = blob.GetSharedAccessSignature(sasConstraints);

    //Return the URI string for the container, including the SAS token.
    return blob.Uri + sasBlobToken;
}

在 Main() 方法的底部,调用 Console.ReadLine() 之前,添加以下代码行,以调用 GetBlobSasUri() 并将共享访问签名 URI 写入控制台窗口:At the bottom of the Main() method, add the following lines to call GetBlobSasUri(), before the call to Console.ReadLine(), and write the shared access signature URI to the console window:

//Generate a SAS URI for a blob within the container, without a stored access policy.
Console.WriteLine("Blob SAS URI: " + GetBlobSasUri(container));
Console.WriteLine();

编译并且运行以输出新 Blob 的共享访问签名 URI。Compile and run to output the shared access signature URI for the new blob. 该 URI 与以下类似:The URI will be similar to the following:

https://storageaccount.blob.core.chinacloudapi.cn/sascontainer/sasblob.txt?sv=2012-02-12&st=2013-04-12T23%3A37%3A08Z&se=2013-04-13T00%3A12%3A08Z&sr=b&sp=rw&sig=dF2064yHtc8RusQLvkQFPItYdeOz3zR8zHsDMBi4S30%3D

在容器上创建存储访问策略Create a stored access policy on the container

现在来在容器上创建一个存储访问策略,该策略定义与其相关联的任何共享访问签名的约束。Now let's create a stored access policy on the container, which will define the constraints for any shared access signatures that are associated with it.

在前面的示例中,我们指定了开始时间(隐式或显式)、到期时间以及共享访问签名 URI 本身的权限。In the previous examples, we specified the start time (implicitly or explicitly), the expiry time, and the permissions on the shared access signature URI itself. 接下来的示例在存储访问策略上指定这些内容,而不是在共享访问签名上指定。In the following examples, we specify these on the stored access policy, not on the shared access signature. 这样做将使我们不必重新发布共享访问签名即可更改这些约束。Doing so enables us to change these constraints without reissuing the shared access signature.

可以使一个或多个约束作用于共享访问签名,使其余的约束作用于存储访问策略。It's possible to have one or more of the constraints on the shared access signature, and the remainder on the stored access policy. 但只能在其中一个位置指定开始时间、到期时间和权限。However, you can only specify the start time, expiry time, and permissions in one place or the other. 例如,不能同时在共享访问签名和存储访问策略上指定权限。For example, you can't specify permissions on the shared access signature and also specify them on the stored access policy.

向容器添加访问策略时,必须获取容器的现有权限,添加新的访问策略,并设置容器的权限。When you add a stored access policy to a container, you must get the container's existing permissions, add the new access policy, and then set the container's permissions.

添加一个新方法,该方法在窗口上创建一个新的存储访问策略并返回该策略的名称:Add a new method that creates a new stored access policy on a container and returns the name of the policy:

static void CreateSharedAccessPolicy(CloudBlobClient blobClient, CloudBlobContainer container,
    string policyName)
{
    //Get the container's existing permissions.
    BlobContainerPermissions permissions = container.GetPermissions();

    //Create a new shared access policy and define its constraints.
    SharedAccessBlobPolicy sharedPolicy = new SharedAccessBlobPolicy()
    {
        SharedAccessExpiryTime = DateTimeOffset.UtcNow.AddHours(24),
        Permissions = SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.List | SharedAccessBlobPermissions.Read
    };

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

在 Main() 方法的底部,调用 Console.ReadLine() 之前,添加以下代码行,以先清除任何现有访问策略,然后调用 CreateSharedAccessPolicy() 方法:At the bottom of the Main() method, before the call to Console.ReadLine(), add the following lines to first clear any existing access policies, and then call the CreateSharedAccessPolicy() method:

//Clear any existing access policies on container.
BlobContainerPermissions perms = container.GetPermissions();
perms.SharedAccessPolicies.Clear();
container.SetPermissions(perms);

//Create a new access policy on the container, which may be optionally used to provide constraints for
//shared access signatures on the container and the blob.
string sharedAccessPolicyName = "tutorialpolicy";
CreateSharedAccessPolicy(blobClient, container, sharedAccessPolicyName);

清除容器上的访问策略时,必须首先获取容器的现有权限,接着清除权限,再次设置权限。When you clear the access policies on a container, you must first get the container's existing permissions, then clear the permissions, then set the permissions again.

在使用访问策略的容器上生成共享访问签名 URIGenerate a shared access signature URI on the container that uses an access policy

接下来,在之前创建的容器上创建另一个共享访问签名,但这次要将该签名与在之前示例中创建的存储访问策略相关联。Next, we create another shared access signature for the container that we created earlier, but this time we associate the signature with the stored access policy we created in the previous example.

添加一个新方法,为容器生成另一个共享访问签名:Add a new method to generate another shared access signature for the container:

static string GetContainerSasUriWithPolicy(CloudBlobContainer container, string policyName)
{
    //Generate the shared access signature on the container. In this case, all of the constraints for the
    //shared access signature are specified on the stored access policy.
    string sasContainerToken = container.GetSharedAccessSignature(null, policyName);

    //Return the URI string for the container, including the SAS token.
    return container.Uri + sasContainerToken;
}

调用 Console.ReadLine() 之前,在 Main() 方法的底部,添加以下代码行以调用 GetContainerSasUriWithPolicy 方法:At the bottom of the Main() method, before the call to Console.ReadLine(), add the following lines to call the GetContainerSasUriWithPolicy method:

//Generate a SAS URI for the container, using a stored access policy to set constraints on the SAS.
Console.WriteLine("Container SAS URI using stored access policy: " + GetContainerSasUriWithPolicy(container, sharedAccessPolicyName));
Console.WriteLine();

在使用访问策略的 Blob 上生成共享访问签名 URIGenerate a Shared Access Signature URI on the Blob That Uses an Access Policy

最后,添加一个类似方法,创建另一个 Blob 并生成与某一存储访问策略相关联的共享访问签名。Finally, we add a similar method to create another blob and generate a shared access signature that's associated with a stored access policy.

添加一个新方法以便创建 Blob 并且生成共享访问签名:Add a new method to create a blob and generate a shared access signature:

static string GetBlobSasUriWithPolicy(CloudBlobContainer container, string policyName)
{
    //Get a reference to a blob within the container.
    CloudBlockBlob blob = container.GetBlockBlobReference("sasblobpolicy.txt");

    //Upload text to the blob. If the blob does not yet exist, it will be created.
    //If the blob does exist, its existing content will be overwritten.
    string blobContent = "This blob will be accessible to clients via a shared access signature. " +
    "A stored access policy defines the constraints for the signature.";
    MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(blobContent));
    ms.Position = 0;
    using (ms)
    {
        blob.UploadFromStream(ms);
    }

    //Generate the shared access signature on the blob.
    string sasBlobToken = blob.GetSharedAccessSignature(null, policyName);

    //Return the URI string for the container, including the SAS token.
    return blob.Uri + sasBlobToken;
}

调用 Console.ReadLine() 之前,在 Main() 方法的底部,添加以下代码行以调用 GetBlobSasUriWithPolicy 方法:At the bottom of the Main() method, before the call to Console.ReadLine(), add the following lines to call the GetBlobSasUriWithPolicy method:

//Generate a SAS URI for a blob within the container, using a stored access policy to set constraints on the SAS.
Console.WriteLine("Blob SAS URI using stored access policy: " + GetBlobSasUriWithPolicy(container, sharedAccessPolicyName));
Console.WriteLine();

现在,完整的 Main() 方法看起来应如下所示。The Main() method should now look like this in its entirety. 运行它以将共享访问签名 URI 写入控制台窗口,并将它们复制并粘贴到一个文本文件中以在本教程的第二部分中使用。Run it to write the shared access signature URIs to the console window, then copy and paste them into a text file for use in the second part of this tutorial.

static void Main(string[] args)
{
    //Parse the connection string and return a reference to the storage account.
    CloudStorageAccount storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));

    //Create the blob client object.
    CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

    //Get a reference to a container to use for the sample code, and create it if it does not exist.
    CloudBlobContainer container = blobClient.GetContainerReference("sascontainer");
    container.CreateIfNotExists();

    //Generate a SAS URI for the container, without a stored access policy.
    Console.WriteLine("Container SAS URI: " + GetContainerSasUri(container));
    Console.WriteLine();

    //Generate a SAS URI for a blob within the container, without a stored access policy.
    Console.WriteLine("Blob SAS URI: " + GetBlobSasUri(container));
    Console.WriteLine();

    //Clear any existing access policies on container.
    BlobContainerPermissions perms = container.GetPermissions();
    perms.SharedAccessPolicies.Clear();
    container.SetPermissions(perms);

    //Create a new access policy on the container, which may be optionally used to provide constraints for
    //shared access signatures on the container and the blob.
    string sharedAccessPolicyName = "tutorialpolicy";
    CreateSharedAccessPolicy(blobClient, container, sharedAccessPolicyName);

    //Generate a SAS URI for the container, using a stored access policy to set constraints on the SAS.
    Console.WriteLine("Container SAS URI using stored access policy: " + GetContainerSasUriWithPolicy(container, sharedAccessPolicyName));
    Console.WriteLine();

    //Generate a SAS URI for a blob within the container, using a stored access policy to set constraints on the SAS.
    Console.WriteLine("Blob SAS URI using stored access policy: " + GetBlobSasUriWithPolicy(container, sharedAccessPolicyName));
    Console.WriteLine();

    Console.ReadLine();
}

运行 GenerateSharedAccessSignatures 控制台应用程序时,会看到如下输出。When you run the GenerateSharedAccessSignatures console application, you'll see output similar to the following. 它们是在本教程第 2 部分中使用的共享访问签名。These are the shared access signatures you use in Part 2 of the tutorial.

Container SAS URI: https://storagesample.blob.core.chinacloudapi.cn/sascontainer?sv=2016-05-31&sr=c&sig=pFlEZD%2F6sJTNLxD%2FQ26Hh85j%2FzYPxZav6mP1KJwnvJE%3D&se=2017-05-16T16%3A16%3A47Z&sp=wl

Blob SAS URI: https://storagesample.blob.core.chinacloudapi.cn/sascontainer/sasblob.txt?sv=2016-05-31&sr=b&sig=%2FiBWAZbXESzCMvRcm7JwJBK0gT0BtPSWEq4pRwmlBRI%3D&st=2017-05-15T16%3A11%3A48Z&se=2017-05-16T16%3A16%3A48Z&sp=rw

Container SAS URI using stored access policy: https://storagesample.blob.core.chinacloudapi.cn/sascontainer?sv=2016-05-31&sr=c&si=tutorialpolicy&sig=aMb6rKDvvpfiGVsZI2rCmyUra6ZPpq%2BZ%2FLyTgAeec%2Bk%3D

Blob SAS URI using stored access policy: https://storagesample.blob.core.chinacloudapi.cn/sascontainer/sasblobpolicy.txt?sv=2016-05-31&sr=b&si=tutorialpolicy&sig=%2FkTWkT23SS45%2FoF4bK2mqXkN%2BPKs%2FyHuzkfQ4GFoZVU%3D

第 2 部分:创建控制台应用程序来测试共享访问签名Part 2: Create a console application to test the shared access signatures

为了测试在之前的示例中创建的共享访问签名,我们创建第二个控制台应用程序,该应用程序使用这些签名在容器和 Blob 上执行操作。To test the shared access signatures created in the previous examples, we create a second console application that uses the signatures to perform operations on the container and on a blob.

Note

如果自你完成本教程的第一部分后超过 24 小时,则你生成的签名不再有效。If more than 24 hours have passed since you completed the first part of the tutorial, the signatures you generated will no longer be valid. 在这种情况下,应该在第一个控制台应用程序中运行代码,生成全新的共享访问签名以供在本教程的第二部分使用。In this case, you should run the code in the first console application to generate fresh shared access signatures for use in the second part of the tutorial.

在 Visual Studio 中,创建一个新的 Windows 控制台应用程序并将其命名为 ConsumeSharedAccessSignaturesIn Visual Studio, create a new Windows console application and name it ConsumeSharedAccessSignatures. 按照之前的操作,添加对 Microsoft.WindowsAzure.ConfigurationManagerWindowsAzure.Storage 的引用。Add references to Microsoft.WindowsAzure.ConfigurationManager and WindowsAzure.Storage, as you did previously.

在 Program.cs 文件的顶部,添加以下 using 指令:At the top of the Program.cs file, add the following using directives:

using System.IO;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;

在 Main() 方法的正文中,添加以下字符串约束,并且将其值更改为在本教程的第 1 部分中生成的共享访问签名。In the body of the Main() method, add the following string constants, changing their values to the shared access signatures you generated in part 1 of the tutorial.

static void Main(string[] args)
{
    const string containerSAS = "<your container SAS>";
    const string blobSAS = "<your blob SAS>";
    const string containerSASWithAccessPolicy = "<your container SAS with access policy>";
    const string blobSASWithAccessPolicy = "<your blob SAS with access policy>";
}

添加一个方法,尝试使用共享访问签名执行容器操作Add a method to try container operations using a shared access signature

接下来添加一个方法,该方法使用共享访问签名为容器测试一些容器操作。Next, we add a method that tests some container operations using a shared access signature for the container. 共享访问签名用于返回对容器的引用,并且单独基于该签名对容器的访问进行身份验证。The shared access signature is used to return a reference to the container, authenticating access to the container based on the signature alone.

将以下方法添加到 Program.cs:Add the following method to Program.cs:

static void UseContainerSAS(string sas)
{
    //Try performing container operations with the SAS provided.

    //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<ICloudBlob> blobList = new List<ICloudBlob>();

    //Write operation: write a new blob to the container.
    try
    {
        CloudBlockBlob blob = container.GetBlockBlobReference("blobCreatedViaSAS.txt");
        string blobContent = "This blob was created with a shared access signature granting write permissions to the container. ";
        blob.UploadText(blobContent);

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

    //List operation: List the blobs in the container.
    try
    {
        foreach (ICloudBlob blob in container.ListBlobs())
        {
            blobList.Add(blob);
        }
        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();
    }

    //Read operation: Get a reference to one of the blobs in the container and read it.
    try
    {
        CloudBlockBlob blob = container.GetBlockBlobReference(blobList[0].Name);
        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();

    //Delete operation: Delete a blob in the container.
    try
    {
        CloudBlockBlob blob = container.GetBlockBlobReference(blobList[0].Name);
        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();
    }
}

更新 Main() 方法,使用在容器上创建的两个共享访问签名调用 UseContainerSAS():Update the Main() method to call UseContainerSAS() with both of the shared access signatures you created on the container:

static void Main(string[] args)
{
    string containerSAS = "<your container SAS>";
    string blobSAS = "<your blob SAS>";
    string containerSASWithAccessPolicy = "<your container SAS with access policy>";
    string blobSASWithAccessPolicy = "<your blob SAS with access policy>";

    //Call the test methods with the shared access signatures created on the container, with and without the access policy.
    UseContainerSAS(containerSAS);
    UseContainerSAS(containerSASWithAccessPolicy);

    Console.ReadLine();
}

添加一个方法,尝试使用共享访问签名执行 Blob 操作Add a method to try blob operations using a shared access signature

最后,添加一个方法,该方法在 Blob 上使用共享访问签名测试一些 Blob 操作。Finally, we add a method that tests some blob operations using a shared access signature on the blob. 在本用例中,我们使用在共享访问签名中传入的构造函数 CloudBlockBlob(String) 返回对该 Blob 的引用。In this case, we use the constructor CloudBlockBlob(String), passing in the shared access signature, to return a reference to the blob. 无需其他身份验证;它仅基于签名。No other authentication is required; it's based on the signature alone.

将以下方法添加到 Program.cs:Add the following method to Program.cs:

static void UseBlobSAS(string sas)
{
    //Try performing blob operations using the SAS provided.

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

    //Write operation: Write a new blob to the container.
    try
    {
        string blobContent = "This blob was created with a shared access signature granting write permissions to the blob. ";
        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();
    }

    //Read operation: Read the contents of the blob.
    try
    {
        MemoryStream msRead = new MemoryStream();
        using (msRead)
        {
            blob.DownloadToStream(msRead);
            msRead.Position = 0;
            using (StreamReader reader = new StreamReader(msRead, true))
            {
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    Console.WriteLine(line);
                }
            }
        }
        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();
    }

    //Delete operation: Delete the blob.
    try
    {
        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();
    }
}

更新 Main() 方法,使用在 Blob 上创建的两个共享访问签名调用 UseBlobSAS():Update the Main() method to call UseBlobSAS() with both of the shared access signatures that you created on the blob:

static void Main(string[] args)
{
    string containerSAS = "<your container SAS>";
    string blobSAS = "<your blob SAS>";
    string containerSASWithAccessPolicy = "<your container SAS with access policy>";
    string blobSASWithAccessPolicy = "<your blob SAS with access policy>";

    //Call the test methods with the shared access signatures created on the container, with and without the access policy.
    UseContainerSAS(containerSAS);
    UseContainerSAS(containerSASWithAccessPolicy);

    //Call the test methods with the shared access signatures created on the blob, with and without the access policy.
    UseBlobSAS(blobSAS);
    UseBlobSAS(blobSASWithAccessPolicy);

    Console.ReadLine();
}

运行该控制台应用程序并观察输出,查看对各个签名允许的操作。Run the console application and observe the output to see which operations are permitted for which signatures. 控制台窗口中的输出将与下面的输出类似:The output in the console window will look similar to the following:

Write operation succeeded for SAS https://storagesample.blob.core.chinacloudapi.cn/sascontainer?sv=2016-05-31&sr=c&sig=32EaQGuFyDMb3yOAey3wq%2B%2FLwgPQxAgSo7UhzLdyIDU%3D&se=2017-05-16T15%3A41%3A20Z&sp=wl

List operation succeeded for SAS https://storagesample.blob.core.chinacloudapi.cn/sascontainer?sv=2016-05-31&sr=c&sig=32EaQGuFyDMb3yOAey3wq%2B%2FLwgPQxAgSo7UhzLdyIDU%3D&se=2017-05-16T15%3A41%3A20Z&sp=wl

Read operation failed for SAS https://storagesample.blob.core.chinacloudapi.cn/sascontainer?sv=2016-05-31&sr=c&sig=32EaQGuFyDMb3yOAey3wq%2B%2FLwgPQxAgSo7UhzLdyIDU%3D&se=2017-05-16T15%3A41%3A20Z&sp=wl
Additional error information: The remote server returned an error: (403) Forbidden.

Delete operation failed for SAS https://storagesample.blob.core.chinacloudapi.cn/sascontainer?sv=2016-05-31&sr=c&sig=32EaQGuFyDMb3yOAey3wq%2B%2FLwgPQxAgSo7UhzLdyIDU%3D&se=2017-05-16T15%3A41%3A20Z&sp=wl
Additional error information: The remote server returned an error: (403) Forbidden.

...

后续步骤Next Steps