首页 > 解决方案 > 如何使用服务主体在 Angular 中使用 C# 访问 Azure Blob 容器图像

问题描述

除了连接字符串、SAS 令牌和其他方法,我们如何使用“服务主体 (OAuth)”身份验证来实现功能。

服务主体通常提供来自 Azure 的“客户端 ID”、“客户端密码”和“租户 ID”值。

标签: azureasp.net-mvc-5azure-blob-storage

解决方案


解决此问题的步骤如下:

  • 生成 OAuth 令牌
  • 创建令牌凭据对象。
  • 获取 Azure 云容器参考。
  • 获取 blob 引用,读取到流并转换为 base 64 字节
  • 在 Angular 6+ 页面中显示字节数组图像

命名空间:

using Microsoft.IdentityModel.Clients.ActiveDirectory;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Blob;

第 1 步:生成 OAuth 令牌- 使用客户端 ID 和客户端密码,生成访问令牌。我们稍后将使用它进行身份验证。

public string GetUserOAuthToken()
{
    const string ResourceId = "https://storage.azure.com/";
    const string AuthInstance = "https://login.microsoftonline.com/{0}/";
    string authority = string.Format(CultureInfo.InvariantCulture, AuthInstance, ConfigHelper.AzStorAccTenantId);
    AuthenticationContext authContext = new AuthenticationContext(authority);
    var clientCred = new ClientCredential(ConfigHelper.AzStorAccClientId, ConfigHelper.AzStorAccClientSecret);
    AuthenticationResult result = authContext.AcquireTokenAsync(ResourceId, clientCred).Result;
    return result.AccessToken;
}

第 2 步:创建令牌凭证对象

public bool GenerateTokenCredentials()
{
    if (string.IsNullOrEmpty(authenticationError))
    {
        string authenticationResult = GetUserOAuthToken();
        if (string.IsNullOrEmpty(authenticationResult))
        {
            return false;
        }
        else
        {
            _tokenCredentials = new TokenCredential(authenticationResult);
            //_tokenCredentials is a global object
            return true;
        }
    }
    else
    {
        return false;
    }
}

步骤 3:获取 Azure 云容器参考

public CloudBlobContainer CreateCloudBlobContainer()
{
    try
    {
        GenerateTokenCredentials();
        StorageCredentials storageCredentials = new StorageCredentials(_tokenCredentials);
        CloudStorageAccount cloudStorageAccount = new CloudStorageAccount(storageCredentials, ConfigHelper.AzStorAccName, ConfigHelper.AzStorageEndPoint, useHttps: true);
        CloudBlobClient blobClient = cloudStorageAccount.CreateCloudBlobClient();
        return blobClient.GetContainerReference(ConfigHelper.AzStorAccBlobContName);
    }
    catch (Exception ex)
    {

    }
    return null;
}

第 4 步:获取 blob 引用,读取到流,并转换为 base 64 字节

public async Task<string> DownloadFile(string blobFileName)
{
    try
    {
        CloudBlobContainer blobContainer = CreateCloudBlobContainer();
        var blob = blobContainer.GetBlobReference(blobFileName);
        blob.FetchAttributes();
        var stream = await blob.OpenReadAsync();
        var byteData = ReadFully(stream);
        string byteImageUrl = string.Format("data:image/{0};base64," + Convert.ToBase64String(byteData), GetBlobImageExtension(blobFileName));
        return byteImageUrl;
    }
    catch (Exception ex)
    {

    }
    return string.Empty;
}

辅助私有方法

private byte[] ReadFully(Stream input)
{
    byte[] buffer = new byte[16 * 1024];
    using (MemoryStream ms = new MemoryStream())
    {
        int read;
        while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
        {
            ms.Write(buffer, 0, read);
        }
        return ms.ToArray();
    }
}

private string GetBlobImageExtension(string blobFileName)
{
    string extension = Path.GetExtension(blobFileName).Trim().ToLower().Replace(".", string.Empty);
    string formattedExtensionForByteArray = !string.IsNullOrEmpty(extension) ? extension.Equals("svg") ? extension + "+xml" : extension : string.Empty;
    return formattedExtensionForByteArray;
}

第 5 步:在 Angular 6+ 中显示字节数组图像

<img [src]="LogoFileName" class="logo" />
  • 打字稿
LogoFileName: SafeResourceUrl;
this.LogoFileName = this.sanitizer.bypassSecurityTrustResourceUrl(responseLogoFileName);

这是一个完整的工作示例,用于使用 Azure Blobs 容器映像并在不将它们下载到驱动器的情况下显示它们。


推荐阅读