Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Microsoft.WindowsAzure.Storage创建共享访问令牌返回403_Azure_Azure Storage_Azure Storage Blobs - Fatal编程技术网

使用Microsoft.WindowsAzure.Storage创建共享访问令牌返回403

使用Microsoft.WindowsAzure.Storage创建共享访问令牌返回403,azure,azure-storage,azure-storage-blobs,Azure,Azure Storage,Azure Storage Blobs,我有一个相当简单的方法,使用新的存储API创建SAS并将blob从一个容器复制到另一个容器 我正试图使用它在存储帐户之间复制blob。因此,我有两个存储帐户,使用完全相同的容器,我正在尝试将blob从存储帐户的容器复制到另一个存储帐户的容器 我不知道SDK是否是为此而构建的,但这似乎是一个常见的场景 一些补充资料: 我在目标容器上创建令牌。 是否需要在源和目标上创建该令牌?注册令牌需要时间吗?我是否需要为每个请求创建它,或者每个令牌“生存期”只创建一次 我应该提到403是一个未经授权的结果htt

我有一个相当简单的方法,使用新的存储API创建SAS并将blob从一个容器复制到另一个容器

我正试图使用它在存储帐户之间复制blob。因此,我有两个存储帐户,使用完全相同的容器,我正在尝试将blob从存储帐户的容器复制到另一个存储帐户的容器

我不知道SDK是否是为此而构建的,但这似乎是一个常见的场景

一些补充资料:

  • 我在目标容器上创建令牌。 是否需要在源和目标上创建该令牌?注册令牌需要时间吗?我是否需要为每个请求创建它,或者每个令牌“生存期”只创建一次 我应该提到403是一个未经授权的结果http错误代码

      private static string CreateSharedAccessToken(CloudBlobClient blobClient, string containerName)
        {
            var container = blobClient.GetContainerReference(containerName);
            var blobPermissions = new BlobContainerPermissions();
    
            // The shared access policy provides read/write access to the container for 10 hours:
    
            blobPermissions.SharedAccessPolicies.Add("SolutionPolicy", new SharedAccessBlobPolicy()
            {
                // To ensure SAS is valid immediately we don’t set start time 
                // so we can avoid failures caused by small clock differences:
    
                SharedAccessExpiryTime = DateTime.UtcNow.AddHours(1),
                Permissions = SharedAccessBlobPermissions.Write |
                              SharedAccessBlobPermissions.Read
            });
    
    
            blobPermissions.PublicAccess = BlobContainerPublicAccessType.Blob; 
            container.SetPermissions(blobPermissions);
    
            return container.GetSharedAccessSignature(new SharedAccessBlobPolicy(), "SolutionPolicy");
    
        }
    
    接下来,我使用此令牌调用复制操作,该操作返回403:

      var uri = new Uri(srcBlob.Uri.AbsoluteUri + blobToken);
                destBlob.StartCopyFromBlob(uri);
    
    我的Azure.Storage版本是2.1.0.2

    以下是案例中的完整复制方法,有助于:

        private static void CopyBlobs(
            CloudBlobContainer srcContainer, string blobToken,
            CloudBlobContainer destContainer)
        {
            var srcBlobList
                = srcContainer.ListBlobs(string.Empty, true, BlobListingDetails.All); // set to none in prod (4perf)
    
            //// get the SAS token to use for all blobs 
            //string token = srcContainer.GetSharedAccessSignature(
            //    new SharedAccessBlobPolicy(), "SolutionPolicy");
    
            bool pendingCopy = true;
    
            foreach (var src in srcBlobList)
            {
                var srcBlob = src as ICloudBlob;
    
                // Determine BlobType:
    
                ICloudBlob destBlob;
                if (srcBlob.Properties.BlobType == BlobType.BlockBlob)
                {
                    destBlob = destContainer.GetBlockBlobReference(srcBlob.Name);
                }
                else
                {
                    destBlob = destContainer.GetPageBlobReference(srcBlob.Name);
                }
    
                // Determine Copy State:
    
                if (destBlob.CopyState != null)
                {
                    switch (destBlob.CopyState.Status)
                    {
                        case CopyStatus.Failed:
                            log.Info(destBlob.CopyState);
                            break;
    
                        case CopyStatus.Aborted:
                            log.Info(destBlob.CopyState);
                            pendingCopy = true;
                            destBlob.StartCopyFromBlob(destBlob.CopyState.Source);
                            return;
    
                        case CopyStatus.Pending:
                            log.Info(destBlob.CopyState);
                            pendingCopy = true;
                            break;
                    }
                }
    
    
                // copy using only Policy ID:
                var uri = new Uri(srcBlob.Uri.AbsoluteUri + blobToken);
                destBlob.StartCopyFromBlob(uri);
    
    
                //// copy using src blob as SAS
                //var source = new Uri(srcBlob.Uri.AbsoluteUri + token);
                //destBlob.StartCopyFromBlob(source);
    
            }
        }
    
    最后是账户和客户(审查)代码:


    当我使用REST客户端时,这似乎有效。。。有什么想法吗

    此任务不需要共享访问令牌。我有两个账户,效果很好:

            var accountSrc = new CloudStorageAccount(credsSrc, true);
            var accountDest = new CloudStorageAccount(credsSrc, true);
    
            var blobClientSrc = accountSrc.CreateCloudBlobClient();
            var blobClientDest = accountDest.CreateCloudBlobClient();
    
    
            // Set permissions on the container.
            var permissions = new BlobContainerPermissions {PublicAccess = BlobContainerPublicAccessType.Blob};
            srcContainer.SetPermissions(permissions);
            destContainer.SetPermissions(permissions);
    
    
       //grab the blob
            var sourceBlob = srcContainer.GetBlockBlobReference("FOO");
            var destinationBlob = destContainer.GetBlockBlobReference("BAR");
    
            //create a new blob
            destinationBlob.StartCopyFromBlob(sourceBlob);
    

    因为两个CloudStorageAccount对象都指向同一个帐户,所以不使用SAS令牌进行复制就可以了,正如您刚才提到的那样

    另一方面,您需要一个可公开访问的blob或SAS令牌从另一个帐户进行复制。因此,您的尝试是正确的,但您建立了一个容器级访问策略,该策略最多需要30秒才能生效,如中所述。在此间隔期间,与存储的访问策略关联的SAS令牌将失败,状态代码403(禁止),直到访问策略变为活动状态


    我想指出的另一点是;调用Get*BlobReference创建新的blob对象时,在执行Get/HEAD操作(如FetchAttributes)之前,不会填充CopyState属性。

    请考虑此问题:

    var uri = new Uri(srcBlob.Uri.AbsoluteUri + blobToken);
    
    可能您正在调用Uri的“ToString”方法,该方法生成url的“可编辑”版本。如果blobToken包含特殊字符,例如“+”,这将在存储服务器上导致令牌格式错误,拒绝授予您访问权限

    改用这个:

    String uri = srcBlob.Uri.AbsoluteUri + blobToken;
    

    从您创建SAS到使用URL进行复制之间有多长时间?它会立即发生;我调用了SAS方法,并在几秒钟后调用StartCopyFromBlob()api调用。这可能与uri编码有关吗?我曾看到报告称REST客户端可以工作,但Azure SDK失败,但没有找到解决方案。我刚刚意识到问题在于它是在两个不同的帐户之间运行的-我认为这意味着我需要两个帐户(目标和源)的信誉?我不确定SAS将如何跨blob内容服务器工作。如果您拥有这两个帐户,那么是的,您所做的一切都很好。我对SAS的猜测是时钟漂移。创建SAS时,您给了它一个过期时间,但没有给它一个开始时间,这意味着它立即启动。服务器上的时钟可能会相互偏移一点,这意味着SAS可能无法立即工作。答案是在过去几分钟内创建具有启动时间的SAS。
    String uri = srcBlob.Uri.AbsoluteUri + blobToken;