【问题标题】:How can you copy a blob in a container with public access set to 'Private'?如何在公共访问设置为“私有”的容器中复制 blob?
【发布时间】:2021-08-28 15:18:56
【问题描述】:

我需要能够将 Blob 从 1 个存储帐户中的容器复制到另一个存储帐户中的容器中。以前,源容器的公共访问权限设置为“容器”。我使用连接字符串连接到帐户,然后获取对 blob 的引用。

我正在使用 StartCopyAsync(sourceBlob)。当容器将公共访问权限设置为容器时,这原本可以正常工作。现在它抛出“指定的资源不存在”的 StorageException。这是权限问题吗?我本来希望一条错误消息说我没有权限。我可以看到资源在容器中。

假设这是一个权限问题,有没有办法从公共访问设置为“私有”的容器中复制 blob?文档建议可以通过“授权请求”来完成,但你是怎么做的呢?

更新

我尝试了 Gaurav Mantri 的建议,但目前收到“此请求无权执行此操作”的错误。这是我的代码:

    private async Task<FileActionResult> CopyBlob(string blobName, string sourceBlobSasToken, string sourceBlobName, CloudBlockBlob targetBlob)
    {
        try
        {
            await targetBlob.StartCopyAsync(new Uri(sourceBlobSasToken));
            var targetBlobRef = await _connectionFactory.GetContainerConnection(BlobContainerType.myTargetContainer).GetBlobReferenceFromServerAsync(targetBlob.Name);

            while (targetBlobRef.CopyState.Status == CopyStatus.Pending)
            {
                await Task.Delay(500);
                targetBlobRef = await _connectionFactory.GetContainerConnection(BlobContainerType.myTargetContainer).GetBlobReferenceFromServerAsync(targetBlob.Name);
            }

            if (targetBlobRef.CopyState.Status == CopyStatus.Success)
            {
                return new FileActionResult(blobName, true);
            }
            else
            {
                var errorMessage = $"{blobName} failed to copy from '{sourceBlobName}' to '{targetBlob}'. Status: {targetBlobRef.CopyState.Status}";
                _logServiceApi.Trace(errorMessage);
                return new FileActionResult(blobName, false, errorMessage);
            }
        }
        catch (StorageException ex)
        {
            _logServiceApi.LogException(ex);
            return new FileActionResult(blobName, false, ex.Message);
        }
        catch (AggregateException ex)
        {
            _logServiceApi.LogException(ex);
            return new FileActionResult(blobName, false, ex.Message);
        }
    }

'sourceBlobSasToken'是通过这段代码获取并传入的:

    public string GetFileStorageBlobSasUri(BlobContainerType blobContainer, string fileName, double tokenDuration, long? projectId = null)
    {
        var blob = GetBlockBlob(blobContainer, fileName, projectId);

        var adHocPolicy = new SharedAccessBlobPolicy()
        {
            SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(tokenDuration),
            Permissions = SharedAccessBlobPermissions.Read
        };

        var sasContainerToken = blob.GetSharedAccessSignature(adHocPolicy);
        return blob.Uri + sasContainerToken;
    } 

【问题讨论】:

  • 您的连接字符串是否有 AccountName 和 AccountKey?像这样: string connectionString = string.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}", account, key);
  • @JoelCochran - 是的。我可以通过门户访问这两个帐户和所有容器,所以我刚刚获取了两者的连接字符串,并在请求中使用它们。

标签: c# azure azure-blob-storage


【解决方案1】:

您似乎无权访问另一个容器的 blob。

好吧,如果要访问 blob,您可以创建身份验证请求。您将需要您的帐户名和密钥来创建一个授权标头,该标头与访问 Blob 的请求一起传递。如果您的请求中没有此授权标头,则该请求将被拒绝。

您也可以访问https://docs.microsoft.com/en-us/azure/storage/blobs/anonymous-read-access-configure?tabs=portal 了解更多信息。

【讨论】:

  • 这不是连接字符串的目的,因为它包含帐户密钥吗?
  • 是的,连接字符串很适合连接到 blob。请同时检查锁定/政策。您可能只有对该容器/blob 的只读权限。
【解决方案2】:

确实是权限问题。要使复制 blob 操作正常工作,源 blob 必须可公开访问。来自这个link

当您的容器的 ACL 公开时,源 blob 可以公开访问,即任何人都可以通过其 URL 直接访问该 blob。但是,一旦将容器的 ACL 更改为私有,源 blob 就不再可公开访问。

要解决您的问题,您需要为源 blob 创建一个至少具有 Read 权限的 SAS URL,并在您的 StartCopyAsync 方法中使用该 SAS URL。

【讨论】:

  • 感谢您的信息
  • 我确信这会起作用,但目前我遇到了一个错误。我已经更新了这个问题。如您所见,我现在正在生成一个 SAS 令牌并以 1 分钟的持续时间将其传入。但是,它会在一秒钟内出错。请看一下。我正在将此作为单元测试的一部分进行测试,所以它可能是我正在运行的用户吗?
  • 你能分享一下你的sourceBlobSasToken 是什么样子的吗?另外,请检查您的存储帐户是否允许基于共享访问签名的操作。您可以通过查看 Azure 门户中存储帐户的 Configuration 部分中的 Allow storage account key access 设置来找到此信息。
  • “允许存储帐户密钥访问”已启用。
  • 在这种情况下请分享您的sourceBlobSasToken。只需混淆帐户名称和sig 部分。
猜你喜欢
  • 2020-01-12
  • 2018-03-30
  • 1970-01-01
  • 2015-07-12
  • 2015-05-03
  • 1970-01-01
  • 2014-03-30
  • 2015-06-09
  • 2018-12-06
相关资源
最近更新 更多