How to configure CORS setting for Blob storage in

2019-04-07 23:37发布

问题:

I have created several containers in a azure storage and also uploaded some files into these containers. Now I need to give domain level access to the container/blobs. So I tried it from code level like below.

        CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
        CloudConfigurationManager.GetSetting("StorageConnectionString"));

        CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
        ServiceProperties blobServiceProperties = new ServiceProperties();
            blobServiceProperties.Cors.CorsRules.Add(new CorsRule(){
                AllowedHeaders = new List<string>() {"*"},
                ExposedHeaders = new List<string>() {"*"},
                AllowedMethods = CorsHttpMethods.Post | CorsHttpMethods.Put | CorsHttpMethods.Get | CorsHttpMethods.Delete ,
                AllowedOrigins = new List<string>() { "http://localhost:8080/"},
                MaxAgeInSeconds = 3600,
            });

          blobClient.SetServiceProperties(GetBlobServiceProperties());  

But above code seems to be work if I am creating everything from code (Correct me if I am wrong). I also find setting like below Here,

 <CorsRule>
  <AllowedOrigins>http://www.contoso.com, http://www.fabrikam.com</AllowedOrigins>
  <AllowedMethods>PUT,GET</AllowedMethods>
  <AllowedHeaders>x-ms-meta-data*,x-ms-meta-target,x-ms-meta-source</AllowedHeaders>
  <ExposedHeaders>x-ms-meta-*</ExposedHeaders>
  <MaxAgeInSeconds>200</MaxAgeInSeconds>
</CorsRule>

But I didn't get where this code have to put. I mean in which file. Or is there any setting for CORS while creating container or blob from azure portal. Please assist. Any help would be appreciable. Thanks!

回答1:

The following answers the question that was actually asked in the title. It appears the questioner already knew how to do this largely from his code, but here is my answer to this. Unfortunately the code samples MS has put out has been far from easy or clear, so I hope this helps someone else. In this solution all you need is a CloudStorageAccount instance, which you can call this function from then (as an extension method).

// USAGE:

        // -- example usage (in this case adding a wildcard CORS rule to this account --

        CloudStorageAccount acc = getYourStorageAccount();

        acc.SetCORSPropertiesOnBlobService(cors => {
            var wildcardRule = new CorsRule() { AllowedMethods = CorsHttpMethods.Get, AllowedOrigins = { "*" } };
            cors.CorsRules.Add(wildcardRule);
            return cors;
        });

// CODE:

    /// <summary>
    /// Allows caller to replace or alter the current CorsProperties on a given CloudStorageAccount.
    /// </summary>
    /// <param name="storageAccount">Storage account.</param>
    /// <param name="alterCorsRules">The returned value will replace the 
    /// current ServiceProperties.Cors (ServiceProperties) value. </param>
    public static void SetCORSPropertiesOnBlobService(this CloudStorageAccount storageAccount,
        Func<CorsProperties, CorsProperties> alterCorsRules)
    {
        if (storageAccount == null || alterCorsRules == null) throw new ArgumentNullException();

        CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

        ServiceProperties serviceProperties = blobClient.GetServiceProperties();

        serviceProperties.Cors = alterCorsRules(serviceProperties.Cors) ?? new CorsProperties();

        blobClient.SetServiceProperties(serviceProperties);
    }

It may be helpful to consider the properties of the CorsRule class:

        CorsRule corsRule = new CorsRule() {
            AllowedMethods = CorsHttpMethods.Get,       // Gets or sets the HTTP methods permitted to execute for this origin
            AllowedOrigins = { "*" },                   // (IList<string>) Gets or sets domain names allowed via CORS.
            //AllowedHeaders = { "*" },                 // (IList<string>) Gets or sets headers allowed to be part of the CORS request
            //ExposedHeaders = null,                    // (IList<string>) Gets or sets response headers that should be exposed to client via CORS
            //MaxAgeInSeconds = 33333                   // Gets or sets the length of time in seconds that a preflight response should be cached by browser
        };


回答2:

Let me try to answer your question. As you know, Azure Storage offers a REST API for managing storage contents. An operation there is Set Blob Service Properties and one of the things you do there is manage CORS rules for blob service. The XML you have included in the question is the request payload for this operation. The C# code you mentioned is actually storage client library which is essentially a wrapper over this REST API written in .Net. So when you use the code above, it actually invokes the REST API and sends the XML.

Now coming to options on setting up CORS rules, there're a few ways you can achieve that. If you're interested in setting them up programmatically, then you can either write some code which consumes the REST API or you could directly use .Net storage client library as you have done above. You could simply create a console application, put the code in there and execute that to set the CORS rule. If you're looking for some tools to do that, then you can try one of the following tools:

  • Azure Management Studio from Cerebrata: http://www.cerebrata.com
  • Cloud Portam: http://www.cloudportam.com (Disclosure: This product is built by me).
  • Azure Storage Explorer (version 6.0): https://azurestorageexplorer.codeplex.com/


回答3:

Its not a good idea to give domain level access to your containers. You can make the container private, upload the files (create blob) and then share it by using Shared Access Policy.

The below code can help you.

static void Main(string[] args)
        {
            var account = CloudStorageAccount.Parse(ConfigurationManager.ConnectionStrings["AzureStorageAccount"].ConnectionString);
            var bClient = account.CreateCloudBlobClient();
            var container = bClient.GetContainerReference("test-share-container-1");
            container.CreateIfNotExists();

            // clear all existing policy
            ClearPolicy(container);

            string newPolicy = "blobsharepolicy";
            CreateSharedAccessPolicyForBlob(container, newPolicy);
            var bUri = BlobUriWithNewPolicy(container, newPolicy);

            Console.ReadLine();
        }

        static void ClearPolicy(CloudBlobContainer container)
        {
            var perms = container.GetPermissions();
            perms.SharedAccessPolicies.Clear();
            container.SetPermissions(perms);
        }       

        static string BlobUriWithNewPolicy(CloudBlobContainer container, string policyName)
        {
            var blob = container.GetBlockBlobReference("testfile1.txt");
            string blobContent = "Hello there !!";
            MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(blobContent));
            ms.Position = 0;
            using (ms)
            {
                blob.UploadFromStream(ms);
            }

            return blob.Uri + blob.GetSharedAccessSignature(null, policyName);
        }

        static void CreateSharedAccessPolicyForBlob(CloudBlobContainer container, string policyName)
        {
            SharedAccessBlobPolicy sharedPolicy = new SharedAccessBlobPolicy()
            {
                SharedAccessExpiryTime = DateTime.UtcNow.AddHours(24),
                Permissions = SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.Read
            };
            var permissions = container.GetPermissions();            
            permissions.SharedAccessPolicies.Add(policyName, sharedPolicy);
            container.SetPermissions(permissions);
        }


<connectionStrings>
    <add name="AzureStorageAccount" connectionString="DefaultEndpointsProtocol=https;AccountName=[name];AccountKey=[key]" />
  </connectionStrings>