简体   繁体   English

Blob存储上的CORS错误

[英]CORS error on Blob Storage

Hi I am trying to develop a file Upload mechanism to Azure blob storage following THIS EXAMPLE , but I am encountering problems with CORS. 嗨,我正在尝试按照本示例开发到Azure blob存储的文件上载机制,但是我遇到了CORS问题。 I have set a sample upload Container. 我已经设置了一个示例上传容器。 I had also enabled CORS for the blob storage (or at least that's what I think since this following code didn't give me any errors): 我还为Blob存储启用了CORS(或者至少这就是我的想法,因为以下代码没有给我任何错误):

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

In the code above the AzureStorage.Default.BlobClient object is a Lazy instantiation of my Blob Client. 在上面的代码中,AzureStorage.Default.BlobClient对象是我的Blob客户端的惰性实例。 The ConfigureCors method is defined as following: 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
        });             
    }

Which should work, since I have already successfully set CORS for Table service using the following code: 这应该起作用,因为我已经使用以下代码成功为Table服务设置了CORS:

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

and I am using the Azure REST API to perform operations on Table Service without problems. 并且我正在使用Azure REST API在Table Service上执行操作而没有问题。 I had also debugged the execution of the C# code while setting the CORS properties and the URL points correctly to my Azure service on the cloud (not the development storage). 在设置CORS属性时,我还调试了C#代码的执行,并且URL正确指向了我在云上(而不是开发存储)上的Azure服务。 My first question is: 我的第一个问题是:

When I try to upload the blocks of a file, following the sample I had linked previosly, I get this error 当我尝试上传文件的块时,按照我之前链接的示例,出现此错误

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 console also says: 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

Which I don't understand since I had already enabled it. 我已经启用它,所以我不了解。 My web app is running on localhost, port 444, on https. 我的Web应用程序在https的本地主机,端口444上运行。

The XHR Request is as follows: 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);
            }
        });

    }

EDIT: I have edited this post after adding some headers to the XHR request so that the 'signature error' is no longer there. 编辑:在向XHR请求添加一些标头之后,我已经编辑了这篇文章,以使“签名错误”不再存在。 The CORS error still persists, though. 但是,CORS错误仍然存​​在。

But, if I create a file and upload it using a web API controller (all server side, see code below) it works without problems: 但是,如果我创建文件并使用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"];
            }
        }

Please make sure you are waiting for 30 seconds after you set container permissions to make sure your changes took effect and the SAS generated using the policy ID is valid. 请确保在设置容器权限后等待30秒,以确保更改生效并且使用策略ID生成的SAS有效。

Also, your code first checks if the policy ID exists and does not update it if it already does. 另外,您的代码会首先检查策略ID是否存在,如果已经存在,则不会对其进行更新。 SAS tokens generated with that ID will stop working 1 day after you first added that policy, because it will never update the policy with a new expiration date/time. 首次添加该策略后,使用该ID生成的SAS令牌将在第1天停止工作,因为它永远不会使用新的到期日期/时间来更新该策略。

Ok it seems that I had to add the blob reference to the URI when making the PUT API call to Azure. 好的,当我对Azure进行PUT API调用时,似乎不得不向URI添加Blob引用。

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

my submitUri javascript variable was then retrieved like so 然后像这样检索我的SubmitUri javascript变量

submitUri = getUploadContainerUrl(file)

where file is the file being uploaded. 其中file是要上传的文件。 I did not include the file.name property in the url path. 我没有在URL路径中包含file.name属性。 The error I got was anyway misleading because it referred to CORS, which instead was correctly enabled. 无论如何,我得到的错误都是令人误解的,因为它涉及CORS,而CORS已正确启用。

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

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