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

时间:2013-10-07 16:46:56

标签: azure azure-storage azure-storage-blobs

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

我正在尝试使用它来复制blob BETWEEN STORAGE帐户。所以我有两个存储帐户,具有完全相同的容器,我正在尝试将存储帐户的容器中的blob复制到另一个存储帐户的容器。

我不知道SDK是否是为此而构建的,但似乎这是一种常见的情况。

其他一些信息:

  1. 我在目标容器上创建令牌。 是否需要在源和目标上创建该令牌?注册令牌需要时间吗?我是否需要为每个请求创建它,或者每个令牌“生命周期”只创建一次?
  2. 我应该提到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);
    
            }
        }
    

    最后是帐户和客户(审核)代码:

           var credentials = new StorageCredentials("BAR", "FOO");
            var account = new CloudStorageAccount(credentials, true);
            var blobClient = account.CreateCloudBlobClient();
            var sasToken = CreateSharedAccessToken(blobClient, "content");
    

    当我使用REST客户端时,这似乎有用......任何想法?

3 个答案:

答案 0 :(得分:1)

还要考虑这个问题:

var uri = new Uri(srcBlob.Uri.AbsoluteUri + blobToken);

可能你正在调用" ToString" Uri的方法,产生"人类可红色"网址的版本。如果blobToken包含特殊的字符,例如" +"这将导致存储服务器上出现令牌格式错误,拒绝为您提供访问权限。

请改用:

String uri = srcBlob.Uri.AbsoluteUri + blobToken;

答案 1 :(得分:0)

此任务不需要共享访问令牌。我最终得到了两个帐户并且工作正常:

        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);

答案 2 :(得分:0)

由于两个CloudStorageAccount对象都指向同一个帐户,因此无需使用SAS令牌进行复制就可以正常工作了。

另一方面,您需要可从其他帐户复制的可公开访问的Blob或SAS令牌。所以你尝试的是正确的,但你建立了一个容器级访问策略,这可能需要30秒才能生效,这也在MSDN中有记录。在此间隔期间,与存储的访问策略关联的SAS令牌将失败,状态码为403(禁止),直到访问策略变为活动状态。

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