4

当我尝试使用使用天蓝色客户端存储库生成的 SAS 密钥时,我不断收到来自 Azure 存储服务的 403 身份验证错误。在调用代码上引发异常。

这是我得到的例外:

StatusMessage:Server failed to authenticate the request. Make sure the value of
Authorization header is formed correctly including the signature.
ErrorCode:AuthenticationFailed

这是正在生成的 SAS 密钥(最后的签名不准确,因为我不想分享它):

https://evinsight.blob.core.windows.net/jimsworld/jellyfish2.png?sv=2012-02-12&se=2013-08-29T03%3A36%3A52Z&sr=b&sp=w&sig=FJALKJFLKASJDF%JLKSDJLK%LJDLFKSDFJKL

这是调用代码:

/// Create the document and file objects and then return the fileAccessToken
/// <param name = "file_name"></param> */
public void GetSasInfoFromEb(string file_name)
{
    /*********************************** EVINSIGHT TESTING CODE ********************************************/
    try
    {
        AzureStorageTester ast = new AzureStorageTester();
        BlobSasUri = ast.getStorageLibrarySas(file_name);
    }
    catch (Exception ex)
    {
        throw ex;
    }
    /***************************************************************************************************************/
}

/// Sends the whole small file to Azure Blob
public void WriteSmallFileToBlob()
{
    int fileId = 0;
    try
    {
        Blob = new CloudBlockBlob(new Uri(BlobSasUri));
        Blob.UploadFromStream(File.InputStream);


        File.InputStream.Close();
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

这是 SAS 生成代码:

    /// <summary>
    ///  Returns the URI similar to how eB does it
    /// </summary>
    /// <param name="blobName">The name of the file being uploaded/downloaded</param>
    /// <returns>The full uri for blob access</returns>
    public string getStorageLibrarySas(string blobName)
    {
        string sasKey;
        string uri;

        setupBlobContainer();

        blobName = blobName.ToLower();
        _blob = _cloudRootContainer.GetBlockBlobReference(blobName);


        sasKey = _blob.GetSharedAccessSignature(new SharedAccessBlobPolicy()
        {
            Permissions = SharedAccessBlobPermissions.Write,
            SharedAccessExpiryTime = DateTime.UtcNow.AddHours(1)
        });

        return string.Format(CultureInfo.InvariantCulture, "{0}{1}", _blob.Uri, sasKey);
    }

    /// Creates the Blob Container
    private void setupBlobContainer()
    {
        try
        {
            Microsoft.WindowsAzure.Storage.Auth.StorageCredentials credentials = new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials(_accountName, _accountKey);

            // Create the storage account with the connection string
            Microsoft.WindowsAzure.Storage.CloudStorageAccount _cloudStorageAccount = new Microsoft.WindowsAzure.Storage.CloudStorageAccount(credentials, true);

            _cloudBlobClient = _cloudStorageAccount.CreateCloudBlobClient();
            _cloudRootContainer = _cloudBlobClient.GetContainerReference(_rootPath.ToLower());
            _cloudRootContainer.CreateIfNotExists();

            BlobContainerPermissions containerPermissions = new BlobContainerPermissions();


            containerPermissions.PublicAccess = BlobContainerPublicAccessType.Off;
            _cloudRootContainer.SetPermissions(containerPermissions);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

有任何想法吗?欣赏它!

4

4 回答 4

4

你的代码对我来说看起来非常好。事实上,我使用您的代码创建了一个示例应用程序,并且一切正常。

您能检查一下sigSAS 令牌的部分吗?特别是在那里寻找+标志。不久前,我在这里看到了一个类似的问题,SAS URL 偶尔会因 403 错误而失败。原来 SAS 令牌中有一个加号,它是space. 由于 SAS 令牌作为 URL 发送,因此+登录令牌被解释为空格并导致 403 错误。

于 2013-08-29T13:16:14.187 回答
3

StartTime 是导致此错误的常见原因(http://blogs.msdn.com/b/kwill/archive/2013/08/28/http-403-server-failed-to-authenticate-the-request-when- using-shared-access-signatures.aspx),但由于您没有指定开始时间,我怀疑您遇到了导致此错误的另一个常见原因 - URI 不正确。请参阅在 Windows Azure 中使用共享访问签名 (SAS) 时,最好使用 Uri.AbsoluteUri() 而不是 Uri.ToString()。

于 2013-08-29T20:00:27.213 回答
1

根据评论,让我将其发布为建议的答案:您可能会看到时钟偏差。尝试将 SAS 开始时间设置为比当前时间早一分钟。默认情况下,开始时间设置为(生成 SAS 的服务器的)当前开始时间。时间设置可能与存储系统的时钟略有偏差。

于 2013-08-29T03:06:20.773 回答
1

事实证明,我的问题集中在与 CLIENT 创建 CONTAINER 上。有两个不同的 Azure 存储库(storage 和 StorageClient)。我使用代码进行存储,但使用旧的 StorageClient 方法,在该方法中,您将完整路径传递到客户端对象“getref ...”方法中以获取容器。事实证明,2.0 存储库只需要传入容器 NAME 即可获取容器。这两个不同的库,对所有东西都有相同的命名,确实让事情变得混乱。

于 2013-08-30T01:38:32.307 回答