通过 MSAL/OAuth 访问 Azure 存储帐户的 Blob

Access Blob of Azure Storage Account via MSAL/OAuth

我必须通过 msal 访问文件并将其上传到 Azure 存储 Blob。因此,我正在根据 Microsoft https://github.com/Azure-Samples/storage-dotnet-azure-ad-msal 的示例关注并配置我的环境。我什至将应用程序注册的服务主体添加到存储帐户的 IAM 中,角色为“Storage Blob 数据所有者”和“Storage Blob 委托人”。访问 Blob 时出现以下异常:

An unhandled exception occurred while processing the request.
RequestFailedException: This request is not authorized to perform this operation using this permission.
RequestId:c0de0782-701e-005b-69cd-a2c6ac000000
Time:2020-10-15T08:27:43.7229905Z
Status: 403 (This request is not authorized to perform this operation using this permission.)
ErrorCode: **AuthorizationPermissionMismatch**

Headers:
Server: Windows-Azure-Blob/1.0,Microsoft-HTTPAPI/2.0
x-ms-request-id: c0de0782-701e-005b-69cd-a2c6ac000000
x-ms-client-request-id: a18e57f6-b22e-48c8-990b-320529a4ef13
x-ms-version: 2019-12-12
x-ms-error-code: AuthorizationPermissionMismatch
Date: Thu, 15 Oct 2020 08:27:43 GMT
Content-Length: 279
Content-Type: application/xml

Azure.Storage.Blobs.BlobRestClient+BlockBlob.UploadAsync_CreateResponse(ClientDiagnostics clientDiagnostics, Response response)

    Stack Query Cookies Headers Routing 

    RequestFailedException: This request is not authorized to perform this operation using this permission. RequestId:c0de0782-701e-005b-69cd-a2c6ac000000 Time:2020-10-15T08:27:43.7229905Z Status: 403 (This request is not authorized to perform this operation using this permission.) ErrorCode: AuthorizationPermissionMismatch Headers: Server: Windows-Azure-Blob/1.0,Microsoft-HTTPAPI/2.0 x-ms-request-id: c0de0782-701e-005b-69cd-a2c6ac000000 x-ms-client-request-id: a18e57f6-b22e-48c8-990b-320529a4ef13 x-ms-version: 2019-12-12 x-ms-error-code: AuthorizationPermissionMismatch Date: Thu, 15 Oct 2020 08:27:43 GMT Content-Length: 279 Content-Type: application/xml
        Azure.Storage.Blobs.BlobRestClient+BlockBlob.UploadAsync_CreateResponse(ClientDiagnostics clientDiagnostics, Response response)
        Azure.Storage.Blobs.BlobRestClient+BlockBlob.UploadAsync(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, Uri resourceUri, Stream body, long contentLength, string version, Nullable<int> timeout, byte[] transactionalContentHash, string blobContentType, string blobContentEncoding, string blobContentLanguage, byte[] blobContentHash, string blobCacheControl, IDictionary<string, string> metadata, string leaseId, string blobContentDisposition, string encryptionKey, string encryptionKeySha256, Nullable<EncryptionAlgorithmType> encryptionAlgorithm, string encryptionScope, Nullable<AccessTier> tier, Nullable<DateTimeOffset> ifModifiedSince, Nullable<DateTimeOffset> ifUnmodifiedSince, Nullable<ETag> ifMatch, Nullable<ETag> ifNoneMatch, string ifTags, string requestId, string blobTagsString, bool async, string operationName, CancellationToken cancellationToken)
        System.Threading.Tasks.ValueTask<TResult>.get_Result()
        System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable<TResult>+ConfiguredValueTaskAwaiter.GetResult()
        Azure.Storage.Blobs.Specialized.BlockBlobClient.UploadInternal(Stream content, BlobHttpHeaders blobHttpHeaders, IDictionary<string, string> metadata, IDictionary<string, string> tags, BlobRequestConditions conditions, Nullable<AccessTier> accessTier, IProgress<long> progressHandler, string operationName, bool async, CancellationToken cancellationToken)
        Azure.Storage.Blobs.Specialized.BlockBlobClient+<>c__DisplayClass48_0+<<GetPartitionedUploaderBehaviors>b__0>d.MoveNext()
        Azure.Storage.PartitionedUploader<TServiceSpecificArgs, TCompleteUploadReturn>.UploadInternal(Stream content, TServiceSpecificArgs args, IProgress<long> progressHandler, bool async, CancellationToken cancellationToken)
        Azure.Storage.Blobs.BlobClient.StagedUploadInternal(Stream content, BlobUploadOptions options, bool async, CancellationToken cancellationToken)
        Azure.Storage.Blobs.BlobClient.UploadAsync(Stream content)
        WebApp_OpenIDConnect_DotNet.Controllers.HomeController.CreateBlob(TokenAcquisitionTokenCredential tokenCredential) in HomeController.cs

                    await blobClient.UploadAsync(stream);

WebApp_OpenIDConnect_DotNet.Controllers.HomeController.Blob() in HomeController.cs

                string message = await CreateBlob(new TokenAcquisitionTokenCredential(_tokenAcquisition));

Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor+TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, object controller, object[] arguments)
System.Threading.Tasks.ValueTask<TResult>.get_Result()
System.Runtime.CompilerServices.ValueTaskAwaiter<TResult>.GetResult()
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Logged|12_1(ControllerActionInvoker invoker)
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ExceptionContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

我做错了什么?我想念什么?

更新 1

API App注册权限

请确保您已将“存储 Blob 数据所有者”角色授予您正在使用的用户帐户。当我仅将此角色授予我的 SP 时,我遇到了同样的错误,在我将此角色授予我的登录用户帐户后,一切正常。

结果:

在我的容器中: