上传到Azure Blob时,请求的资源上不存在“Access-Control-Allow-Origin”标头

时间:2016-10-12 18:21:18

标签: azure cors azure-storage-blobs

我一直在努力争取这一天。我正在直接测试Azure Blob存储上传并获得可怕的CORS问题。 "XMLHttpRequest cannot load https://tempodevelop.blob.core.windows.net/tmp/a4d8e867-f13e-343f-c6d3-a603…Ym0PlrBn%2BU/UzUs7QUhQw%3D&sv=2014-02-14&se=2016-10-12T17%3A59%3A26.638531. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8000' is therefore not allowed access. The response had HTTP status code 403."

我已经尝试过的事情:

  1. 将CORS设置为所有主机: enter image description here
  2. 尝试在本地和heroku上托管我的应用
  3. 确保我可以使用其他工具(Azure存储资源管理器)上传文件
  4. 将我的AccessPolicy配置为'rwdl',我肯定会获得访问签名(在单元测试中验证)。
  5. 整个代码可在此处找到:https://github.com/mikebz/azureupload

    但相关部分在这里,前端上传:

    <script>
    
        /* 
         * not a true GUID, see here: http://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
         */ 
        function guid() {
            function s4() {
                return Math.floor((1 + Math.random()) * 0x10000)
                .toString(16)
                .substring(1);
            }
            return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
                s4() + '-' + s4() + s4() + s4();
        }
    
        function startUpload() {   
            var fileName = guid();
    
            jQuery.getJSON("/formfileupload/signature/" + fileName , function(data) {
                    console.log("got a signature: " + data.bloburl);
                    uploadFile(data.bloburl, data.signature);
                })
                .fail(function(jqxhr, textStatus, error) {
                    console.log( "error: " + textStatus + " - " + error );
                })
        }
        
        function uploadFile(bloburl, signature) {        
            var xhr = new XMLHttpRequest();
            fileData = document.getElementById('fileToUpload').files[0];
            xhr.open("PUT", bloburl + "?" + signature);
            xhr.setRequestHeader('x-ms-blob-type', 'BlockBlob');
            xhr.setRequestHeader('x-ms-blob-content-type', fileData.type);
            result = xhr.send(fileData);
        }
    </script>

    python中的签名生成代码在这里:

    def generate_access_signature(self, filename):
        """
        calls the Azure Web service to generate a temporary access signature.
        """
        blob_service = BlobService(
            account_name=self.account_name, 
            account_key=self.account_key
        )
    
        expire_at = datetime.utcnow()
        expire_at = expire_at + timedelta(seconds = 30)
        access_policy = AccessPolicy(permission="rwdl", expiry=expire_at.isoformat())
    
        sas_token = blob_service.generate_shared_access_signature( 
            container_name="tmp",
            blob_name = filename, 
            shared_access_policy=SharedAccessPolicy(access_policy)
        )
        return sas_token
    

2 个答案:

答案 0 :(得分:5)

根据错误消息[响应具有HTTP状态代码403],可能是服务未启用CORS,或者没有CORS规则与预检请求匹配。细节请参考Cross-Origin Resource Sharing (CORS) Support for the Azure Storage Services。 或者可能是SAS签名不正确。 请尝试进行问题排查

  1. 尝试在Blob服务下检查Azure门户上的CORS设置。因为还有其他服务,如表,队列,文件。 Expected

  2. 您还可以使用Azure explore工具生成SAS令牌 enter image description here

  3. 获取SAS并尝试使用生成的SAS对其进行调试 demo code enter image description here

答案 1 :(得分:1)

感谢Tom和Microsoft的支持,问题已得到解决 解决方案部分#1 - 确保使用Azure存储库for Python版本0.33或更高版本。

这是我的要求文件:

azure-common==1.1.4
azure-nspkg==1.0.0
azure-storage==0.33.0
cffi==1.8.3
cryptography==1.5.2
dj-database-url==0.4.1
Django==1.10.2
enum34==1.1.6
futures==3.0.5
gunicorn==19.6.0
idna==2.1
ipaddress==1.0.17
pep8==1.7.0
psycopg2==2.6.2
pyasn1==0.1.9
pycparser==2.16
python-dateutil==2.5.3
requests==2.11.1
six==1.10.0
whitenoise==3.2.2

第二个问题是生成签名。生成正确签名的代码在此处:

from azure.storage.blob import BlockBlobService, ContainerPermissions
from datetime import datetime, timedelta


class AzureUtils:

    def __init__(self, account_name, account_key):
        if account_name is None:
            raise ValueError("account_name should not be None")
        if account_key is None:
            raise ValueError("account_key should not be None")
        self.account_name = account_name
        self.account_key = account_key

    def generate_access_signature(self, filename):
        """
        calls the Azure Web service to generate a temporary access signature.
        """
        block_blob_service = BlockBlobService(
            account_name=self.account_name,
            account_key=self.account_key
        )

        expire_at = datetime.utcnow()
        expire_at = expire_at + timedelta(seconds=30)

        permissions = ContainerPermissions.READ | ContainerPermissions.WRITE | ContainerPermissions.DELETE | ContainerPermissions.LIST

        sas_token = block_blob_service.generate_container_shared_access_signature(
                "tmp",
                permission=permissions,
                expiry=expire_at
        )

        return sas_token

也可以在此处检索解决方案:https://github.com/mikebz/azureupload