0

我有一个 azure 资源组,其中包含带有 BLOB 容器的 Web 应用服务和存储。我的 Web 应用程序 (.NET Core) 尝试从容器中检索和显示图像。容器对内容没有公共访问权限(访问级别为私有)。我为我的应用程序创建了系统分配的身份,并在存储访问控制 (IAM) 中为其赋予了读者角色。

这就是我在应用程序代码中访问 blob 的方式:

const string blobName = "https://storagename.blob.core.windows.net/img/Coast.jpg";
string storageAccessToken = await GetStorageAccessTokenAsync();
var tokenCredential = new TokenCredential(storageAccessToken);
var storageCredentials = new StorageCredentials(tokenCredential);
var blob = new CloudBlockBlob(new Uri(blobName), storageCredentials);
ImageBlob = blob.Uri;

GetStorageAccessTokenAsync() 这样做:

var tokenProvider = new AzureServiceTokenProvider();
return await tokenProvider.GetAccessTokenAsync("https://storage.azure.com/");

然后图像显示为

<img src="@Model.ImageBlob" />

我的代码中没有任何异常,但来自 BLOB 容器的图像未在浏览器控制台中显示 404 错误(指定的资源不存在)。当我将容器的访问级别更改为“blob”(公共访问)时,应用程序工作正常并显示图像。显然,获取凭据部分有问题,但我找不到任何工作示例,也找不到它实际应该如何工作的详细解释。非常感谢任何帮助。

UDPATE:谢谢所有回复的人。所以,看来我在这里有两个问题。

1)我没有正确获得凭据。我可以看到我创建的“AzureServiceTokenProvider”对象(Microsoft.Azure.Services.AppAuthentication)在运行时具有空属性 PrincipalUsed。

我的应用程序部署到 Azure App Service,它具有系统管理的标识,并且该标识(服务主体)在 Azure 存储中被授予权限(我按照建议将权限从帐户读取器更改为存储 Blob 数据读取器)。

它不应该从当前上下文中获取所有需要的数据吗?如果没有,我可以在这里做什么?

2)我使用错误的方法来显示图像,但由于该应用程序无论如何都无法访问存储,我还无法修复它。

但是 - 在我的情况下,常见的方法是什么?我的意思是没有对存储的公共访问,我使用“CloudBlockBlob”来访问图像。

4

3 回答 3

1

Reader 允许读取控制平面,但不能读取数据平面。您需要的角色是存储 Blob 数据读取器,它提供读取 blob 内容的访问权限。

有关这方面的更多详细信息,请查看:https ://docs.microsoft.com/en-us/azure/role-based-access-control/role-definitions#data-operations-example

于 2019-06-24T17:34:24.230 回答
0

使用时<img src="@Model.ImageBlob" />,浏览器在请求中不发送授权头。在您的代码中,您正在获取令牌,但在获取图像时,令牌并未在授权标头中发送。因此,存储 API 认为这是一个匿名请求。这就是您获得 404 的原因。

您需要在获取图像时发送验证码。这段代码对我有用

public async Task<ActionResult> Image()
        {
            const string blobName = "https://storage.blob.core.windows.net/images/image.png";
            string storageAccessToken = await GetStorageAccessTokenAsync().ConfigureAwait(false);

            var tokenCredential = new TokenCredential(storageAccessToken);
            var storageCredentials = new StorageCredentials(tokenCredential);

            var blob = new CloudBlockBlob(new Uri(blobName), storageCredentials);
            Stream blobStream = blob.OpenRead();
            return File(blobStream, blob.Properties.ContentType, "image.png");
        }

在视图中,我使用

<img src="/Home/Image" />
于 2019-06-27T18:40:58.927 回答
0

最后,我让它工作了。首先,关于从 Azure 存储中获取令牌和图像的部分代码是可以的。我解决了在 RazorPages 应用程序中显示图像的第二个问题,在视图中使用以下代码:

<form asp-page-handler="GetImage" method="get">
    <img src="/MyPageName?handler=GetImage" />
</form>

和模型中的相应代码:

public async Task<ActionResult> OnGetGetImageAsync()
{
   //getting image code and returning FileContentResult
}

但我仍在思考:是否有更简单的方法来做到这一点?像向模型添加图像集合,使用“OnGet ...”处理程序填充它,然后使用视图显示其内容。我没有找到在<img>标签中使用模型属性的方法。有人有什么建议吗?

于 2019-07-07T17:54:44.110 回答