尝试在 Web API 请求上检索 Azure Blob 时出现 403 错误

Posted

技术标签:

【中文标题】尝试在 Web API 请求上检索 Azure Blob 时出现 403 错误【英文标题】:Getting 403 error when trying to retrieve an Azure blob on Web API request 【发布时间】:2017-07-28 10:47:59 【问题描述】:

我正在尝试让经过身份验证的(通过 JWT)GET 请求返回存储在 Azure blob 中的图像。当我在本地机器上运行项目并使用邮递员请求图像并且请求通过时,我确实得到了我请求的图像。但是,一旦我将代码部署到 Azure 并点击相同的端点,我就会得到 403。代码在我尝试调用 DownloadToStreamAsync 的那一行失败。这是我正在使用的代码:

public async Task<BlobDownloadModel> DownloadBlob(Guid blobId)
    
        try
        
            //get picture record
            Picture file = await _media.GetPictureAsync(blobId);

            await _log.CreateLogEntryAsync("got picture record");

            // get string format blob name
            var blobName = file.PictureId.ToString() + file.Extension;

            await _log.CreateLogEntryAsync("got name of blob " + blobName);

            if (!String.IsNullOrEmpty(blobName))
            
                await _log.CreateLogEntryAsync("blob not empty");

                var blob = _container.GetBlockBlobReference(blobName);

                await _log.CreateLogEntryAsync("got blob: " + blob.ToString());

                var ms = new MemoryStream();

                await blob.DownloadToStreamAsync(ms);

                await _log.CreateLogEntryAsync("blob downloaded to memory stream");

                var lastPos = blob.Name.LastIndexOf('/');
                var fileName = blob.Name.Substring(lastPos + 1, blob.Name.Length - lastPos - 1);

                var download = new BlobDownloadModel
                
                    BlobStream = ms,
                    BlobFileName = fileName,
                    BlobLength = blob.Properties.Length,
                    BlobContentType = blob.Properties.ContentType
                ;

                return download;
            
        
        catch(Exception ex)
        
            await _log.CreateLogEntryAsync("exception thrown: " + ex.ToString());
        

如果能得到任何帮助,我将不胜感激。

更新:

我把我的代码改成这个并再次尝试:

public async Task<AzureBlobModel> DownloadBlob(Guid blobId)
    
        try
        
            //get picture record
            Picture file = await _media.GetPictureAsync(blobId);

            await _log.CreateLogEntryAsync("got picture record");

            // get string format blob name
            var blobName = file.PictureId.ToString() + file.Extension;

            await _log.CreateLogEntryAsync("got name of blob " + blobName);

            if (!String.IsNullOrEmpty(blobName))
            
                await _log.CreateLogEntryAsync("blob not empty");

                var blob = _container.GetBlockBlobReference(blobName);

                await _log.CreateLogEntryAsync("got blob: " + blob.ToString());

                // Strip off any folder structure so the file name is just the file name
                var lastPos = blob.Name.LastIndexOf('/');
                var fileName = blob.Name.Substring(lastPos + 1, blob.Name.Length - lastPos - 1);

                await _log.CreateLogEntryAsync("got fileName: " + fileName);

                //await blob.DownloadToStreamAsync(ms);

                await _log.CreateLogEntryAsync("about to open read stream");

                var stream = await blob.OpenReadAsync();

                await _log.CreateLogEntryAsync("opened read stream");

                var result = new AzureBlobModel()
                
                    FileName = fileName,
                    FileSize = blob.Properties.Length,
                    Stream = stream,
                    ContentType = blob.Properties.ContentType
                ;

                await _log.CreateLogEntryAsync("blob downloaded to memory stream");

                return result;

                // Build and return the download model with the blob stream and its relevant info
                //var download = new BlobDownloadModel
                //
                //    BlobStream = ms,
                //    BlobFileName = fileName,
                //    BlobLength = blob.Properties.Length,
                //    BlobContentType = blob.Properties.ContentType
                //;

                //return download;
            
        
        catch(Exception ex)
        
            await _log.CreateLogEntryAsync("exception thrown: " + ex.ToString());
        

        await _log.CreateLogEntryAsync("returning null");

        // Otherwise
        return null;
    

最后一次尝试的日志结果是这样的:

请求已收到并通过身份验证,UTC 时间戳:2017 年 3 月 10 日上午 5:28:26 - 上午 5:28:26 收到的 ID:b3bc7faf-0c86-4ce2-af84-30636825a485 - 5:28:27 AM 得到图片记录-5:28:27 AM 得到 blob b3bc7faf-0c86-4ce2-af84-30636825a485.JPG - 5:28:27 AM的名称 blob 不为空 - 上午 5:28:27 得到 blob:Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob - 5:28:27 AM 得到文件名:b3bc7faf-0c86-4ce2-af84-30636825a485.JPG - 5:28:27 AM 即将打开读取流 - 上午 5:28:27

我能够检索文件/blob 的名称,从而消除了错误的帐户密钥作为问题的罪魁祸首。

解决方案

我能够让我的代码使用以下代码:

public async Task<AzureBlobModel> DownloadBlob(Guid blobId)
    
        try
        
            //get picture record
            Picture file = await _media.GetPictureAsync(blobId);

            // get string format blob name
            var blobName = file.PictureId.ToString() + file.Extension;

            if (!String.IsNullOrEmpty(blobName))
            
                var blob = _container.GetBlockBlobReference(blobName);

                // Strip off any folder structure so the file name is just the file name
                var lastPos = blob.Name.LastIndexOf('/');
                var fileName = blob.Name.Substring(lastPos + 1, blob.Name.Length - lastPos - 1);

                var fileLength = blob.Properties.Length;
                var stream = await blob.OpenReadAsync();

                var result = new AzureBlobModel()
                
                    FileName = fileName,
                    FileSize = blob.Properties.Length,
                    Stream = stream,
                    ContentType = blob.Properties.ContentType
                ;

                return result;
            
        
        catch(Exception ex)
        
            await _log.CreateLogEntryAsync("exception thrown: " + ex.ToString());
        

        await _log.CreateLogEntryAsync("returning null");

        // Otherwise
        return null;
    

【问题讨论】:

【参考方案1】:

但是,一旦我将代码部署到 Azure 并点击相同的端点,我就会得到 403。

首先,请检查您的 Azure 帐户和密钥以确保它们正确无误。其次,请检查服务器上的时钟。存储服务确保请求到达服务的时间不超过 15 分钟。如果您的服务器上的时间与存储服务器上的时间不同步,则会出现 403 错误。

【讨论】:

我再次检查以确保帐户凭据正确。 Web 服务器和 Blob 存储都位于美国西海岸。我假设服务器时间是同步的。你知道我怎么查时间吗? 你用存储模拟器测试吗?如果您部署到 Azure,请确保使用 Azure 存储连接进行更改。还请检查帐户密钥以确保它不会重新生成。很容易检查服务器时间。请尝试获取服务器上的时间,以确保您的手表时间正确。 Jambor,我确定帐户密钥是正确的,我继续并通过在本地计算机上运行 API 进行了测试,并且能够从实时存储帐户中检索图像。我继续截取了请求数据24hr.cloudtimecards.com/File/Download/… 的截图另外,我无法检查 Azure 存储服务器上的时间。我查看了 Azure 门户,但没有运气。【参考方案2】:

我能够使用以下代码解决问题:

public async Task<AzureBlobModel> DownloadBlob(Guid blobId)
    
        try
        
            //get picture record
            Picture file = await _media.GetPictureAsync(blobId);

            // get string format blob name
            var blobName = file.PictureId.ToString() + file.Extension;

            if (!String.IsNullOrEmpty(blobName))
            
                var blob = _container.GetBlockBlobReference(blobName);

                // Strip off any folder structure so the file name is just the file name
                var lastPos = blob.Name.LastIndexOf('/');
                var fileName = blob.Name.Substring(lastPos + 1, blob.Name.Length - lastPos - 1);

                var fileLength = blob.Properties.Length;
                var stream = await blob.OpenReadAsync();

                var result = new AzureBlobModel()
                
                    FileName = fileName,
                    FileSize = blob.Properties.Length,
                    Stream = stream,
                    ContentType = blob.Properties.ContentType
                ;

                return result;
            
        
        catch(Exception ex)
        
            await _log.CreateLogEntryAsync("exception thrown: " + ex.ToString());
        

        await _log.CreateLogEntryAsync("returning null");

        // Otherwise
        return null;
    

【讨论】:

以上是关于尝试在 Web API 请求上检索 Azure Blob 时出现 403 错误的主要内容,如果未能解决你的问题,请参考以下文章

尝试使用 Web api 从 Azure 队列中检索消息文本,但消息文本已编码。我如何删除编码

Azure api 请求被中止:无法创建 SSL/TLS 安全通道。 http客户端在调用一些web api时

使用.net核心Web API和jquery从天蓝色斑点中上传和检索图像

在 AAD 保护的 Azure Web 应用程序中检索访问令牌

Azure广告声明-检索用户名

在 Azure Web 应用程序中为 Web API 启用 CORS