【问题标题】:CORS error on Blob StorageBlob 存储上的 CORS 错误
【发布时间】:2014-08-19 18:28:48
【问题描述】:

您好,我正在尝试按照THIS EXAMPLE 开发一种文件上传机制到 Azure blob 存储,但我遇到了 CORS 问题。 我已经设置了一个示例上传容器。 我还为 blob 存储启用了 CORS(或者至少我是这么认为的,因为下面的代码没有给我任何错误):

var blobServiceProperties = AzureStorage.Default.BlobClient.GetServiceProperties();
            ConfigureCors(blobServiceProperties);
            AzureStorage.Default.BlobClient.SetServiceProperties(blobServiceProperties);

在上面的代码中,AzureStorage.Default.BlobClient 对象是我的 Blob 客户端的延迟实例化。 ConfigureCors 方法定义如下:

private static void ConfigureCors(ServiceProperties serviceProperties)
    {            
        serviceProperties.Cors = new CorsProperties();            
        serviceProperties.Cors.CorsRules.Add(new CorsRule()
        {
            AllowedHeaders = new List<string>() { "*" },
            AllowedMethods = CorsHttpMethods.Put | CorsHttpMethods.Get | CorsHttpMethods.Head | CorsHttpMethods.Post | CorsHttpMethods.Delete,
            AllowedOrigins = new List<string>() { 
                "https://localhost:444",
                "https://xxx.yyy.com" 
            },               
            ExposedHeaders = new List<string>() { "*" },
            MaxAgeInSeconds = 1800 // 30 minutes
        });             
    }

这应该可行,因为我已经使用以下代码成功地为表服务设置了 CORS:

var serviceProperties = AzureStorage.Default.TableClient.GetServiceProperties();
ConfigureCors(serviceProperties);
AzureStorage.Default.TableClient.SetServiceProperties(serviceProperties);

我正在使用 Azure REST API 在表服务上执行操作而没有问题。 我还调试了 C# 代码的执行,同时设置了 CORS 属性,并且 URL 正确指向了我在云上的 Azure 服务(而不是开发存储)。 我的第一个问题是:

当我尝试按照我之前链接的示例上传文件块时,我收到此错误

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://myaccount.blob.core.windows.net/upload-73cca078-9a57-4fd4-a5b9-8012a8bb56bf?sv=2014-02-14&sr=c&si=BlobContainer&sig=mysignature&comp=block&blockid=YmxvY2stMDAwMDAw. This can be fixed by moving the resource to the same domain or enabling CORS.

Chrome 控制台还说:

XMLHttpRequest cannot load https://myaccount.blob.core.windows.net/upload-73cca078-9a57-4fd4-a5b9-8012…6mwSBkT67KIJFrTmwpSNN9slSAq0rbiLxRc%3D&comp=block&blockid=YmxvY2stMDAwMDAw. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://localhost:444' is therefore not allowed access

我不明白,因为我已经启用了它。 我的 Web 应用程序在 https 上的 localhost 端口 444 上运行。

XHR 请求如下:

function commitBlockList() {
        var uri = submitUri + '&comp=blocklist';
        console.log(uri);
        var requestBody = '<?xml version="1.0" encoding="utf-8"?><BlockList>';
        for (var i = 0; i < blockIds.length; i++) {
            requestBody += '<Latest>' + blockIds[i] + '</Latest>';
        }
        requestBody += '</BlockList>';
        console.log(requestBody);
        $.ajax({
            url: uri,
            type: "PUT",
            data: requestBody,
            beforeSend: function (xhr) {
                xhr.setRequestHeader('x-ms-blob-content-type', selectedFile.type);
                xhr.setRequestHeader('Content-Length', requestBody.length);

                xhr.setRequestHeader("x-ms-blob-type", "BlockBlob");
                xhr.setRequestHeader("x-ms-date", "Mon, 18 Aug 2014 13:05:21 GMT");
                xhr.setRequestHeader("x-ms-version", "2012-02-12");
                xhr.setRequestHeader("Authorization", "SharedKey myaccount:d3gXfj6kSp4qVejioDjKQA7dbPyFerDf2iw47RcmGXM=");
            },
            success: function (data, status) {
                console.log(data);
                console.log(status);
            },
            error: function (xhr, desc, err) {
                console.log(xhr);
                console.log(desc);
                console.log(err);
            }
        });

    }

编辑:在向 XHR 请求添加一些标头后,我编辑了这篇文章,以便不再存在“签名错误”。但是,CORS 错误仍然存​​在。

但是,如果我创建一个文件并使用 Web API 控制器(所有服务器端,请参见下面的代码)上传它,它可以正常工作:

[HttpGet]
        public void Test1() {
            PutBlob("upload-73cca078-9a57-4fd4-a5b9-8012a8bb56bf", "test.txt");
        }

        public string CreateAuthorizationHeader(string canonicalizedstring)
        {
            var key = "mykey";
            string signature = string.Empty;
            using (System.Security.Cryptography.HMACSHA256 hmacSha256 = new System.Security.Cryptography.HMACSHA256(Convert.FromBase64String(key)))
            {
                Byte[] dataToHmac = System.Text.Encoding.UTF8.GetBytes(canonicalizedstring);
                signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
            }
            string authorizationHeader = string.Format(CultureInfo.InvariantCulture, "{0} {1}:{2}", "SharedKey", "myaccount", signature);
            return authorizationHeader;
        }

        public void PutBlob(String containerName, String blobName)
        {
            String requestMethod = "PUT";

            String urlPath = String.Format("{0}/{1}", containerName, blobName);

            String storageServiceVersion = "2012-02-12";

            String dateInRfc1123Format = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);

            String content = "my test string";
            UTF8Encoding utf8Encoding = new UTF8Encoding();
            Byte[] blobContent = utf8Encoding.GetBytes(content);
            Int32 blobLength = blobContent.Length;

            const String blobType = "BlockBlob";

            String canonicalizedHeaders = String.Format(
                    "x-ms-blob-type:{0}\nx-ms-date:{1}\nx-ms-version:{2}",
                    blobType,
                    dateInRfc1123Format,
                    storageServiceVersion);
            String canonicalizedResource = String.Format("/{0}/{1}", "citaviweb", urlPath);
            String stringToSign = String.Format(
                    "{0}\n\n\n{1}\n\n\n\n\n\n\n\n\n{2}\n{3}",
                    requestMethod,
                    blobLength,
                    canonicalizedHeaders,
                    canonicalizedResource);
            String authorizationHeader = CreateAuthorizationHeader(stringToSign);

            Uri uri = new Uri(AzureStorage.Default.BlobClient.BaseUri + urlPath);
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
            request.Method = requestMethod;
            request.Headers.Add("x-ms-blob-type", blobType);
            request.Headers.Add("x-ms-date", dateInRfc1123Format);
            request.Headers.Add("x-ms-version", storageServiceVersion);
            request.Headers.Add("Authorization", authorizationHeader);
            request.ContentLength = blobLength;

            using (Stream requestStream = request.GetRequestStream())
            {
                requestStream.Write(blobContent, 0, blobLength);
            }

            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            {
                String ETag = response.Headers["ETag"];
            }
        }

【问题讨论】:

    标签: azure cors azure-storage


    【解决方案1】:

    请确保您在设置容器权限后等待 30 秒,以确保您的更改生效并且使用策略 ID 生成的 SAS 有效。

    此外,您的代码首先会检查策略 ID 是否存在,如果已存在则不会更新它。使用该 ID 生成的 SAS 令牌将在您首次添加该策略后 1 天停止工作,因为它永远不会使用新的到期日期/时间更新该策略。

    【讨论】:

    • 我等了 30 秒或更长时间,并更改了代码以设置策略(请参阅已编辑的问题),但没有任何改变。我的怀疑是,它甚至不是容器权限问题,而是 CORS 的问题。我还调试了用于设置 CORS 属性的“SetServiceProperties”,我看到 URL 是正确的,并且我运行我的应用程序的 URL(https://localhost:444)甚至在那里,所以 CORS属性设置。但后来我不知道为什么它仍然给我这个 CORS 错误。
    【解决方案2】:

    好的,在对 Azure 进行 PUT API 调用时,我似乎必须添加对 URI 的 blob 引用。

    var getUploadContainerUrl = function (file) {            
                var usad = config.accessData.blob;
                var url = usad.uri + "/" + file.name + usad.sharedAccessSignature;
                return url;
            }
    

    然后像这样检索了我的 submitUri javascript 变量

    submitUri = getUploadContainerUrl(file)
    

    file 是正在上传的文件。我没有在 url 路径中包含 file.name 属性。我得到的错误无论如何都具有误导性,因为它引用了 CORS,而它却被正确启用。

    【讨论】:

      猜你喜欢
      • 2021-07-09
      • 2017-09-21
      • 2015-12-07
      • 2018-02-26
      • 2016-08-01
      • 2016-07-24
      • 2017-04-17
      • 1970-01-01
      相关资源
      最近更新 更多