使用 Azure 活动目录访问 Azure 函数时,Blazor 客户端出现 CORS 错误

Blazor Client side get CORS error when accessing Azure Function using Azure Active directory

我已经尝试部署我的 Blazor PWA 2 天了,到目前为止没有任何成功,如果有人知道我做错了什么,我将非常感激。 你好 我可以自己解决大部分问题,但我现在遇到了使用 AAD 的 CORS 问题。

这是我的项目设置:

所以我创建了一个 App 注册,将我的静态网站地址添加为 SPA uri 并取消选中这两个隐式。 在我的 Blazor 客户端 program.cs 中,我添加了以下代码以连接到 AAD:

builder.Services.AddMsalAuthentication(options =>
{
    builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication); //contains clientId, Authority
    options.ProviderOptions.DefaultAccessTokenScopes.Add("https://graph.microsoft.com/User.Read");
    options.ProviderOptions.LoginMode = "redirect";
});

效果也很好,我可以登录,授权查看按预期工作。

问题是当我尝试使用 «Login with Azure Active Directory» 验证 Azure 功能时, 我尝试了快速配置和高级配置(使用 clientId、tenantId)但是当我

从源 'https://*****9.web.core.windows.net' 访问“https://login.windows.net/tenantid/oauth2/authorize ...(从 'https://myfunctionstorage.azurewebsites.net/api/client/list' 重定向)已被 CORS 策略阻止: 请求的资源上不存在 'Access-Control-Allow-Origin' header。如果不透明的响应满足您的需求,请将请求的模式设置为 'no-cors' 以在禁用 CORS 的情况下获取资源。

我当然在 Azure Functions 配置上为我的 Blazor 客户端地址启用了 CORS,但问题似乎与登录 windows uri...

有关

此外,如果我在应用程序注册中启用令牌 ID 隐式流并在浏览器中访问登录名 url,它就可以正常工作。

到目前为止我能找到的所有示例都是关于 msal 1.0 和使用隐式流而不是 SPA 的应用程序注册的,所以它没有帮助...

感谢您的宝贵时间和帮助。

更新: 从昨天开始我做了更多的研究,我认为它可能与我的 HTTPClient 相关,目前我使用的是基本的(只有一个基本地址)。

但我在一些示例中看到,当使用 AAD 客户端时,它需要更多参数,例如:

builder.Services.AddHttpClient("companiesAPI", cl => { cl.BaseAddress = new Uri("https://localhost:5001/api/"); }) .AddHttpMessageHandler(sp => { var handler = sp.GetService<AuthorizationMessageHandler>() .ConfigureHandler( authorizedUrls: new[] { "https://localhost:5001" }, scopes: new[] { "companyApi" } ); return handler; });

是否需要 AuthorizationMessageHandler? 我还看到一些关于需要使用 «use_impersonation» 范围的参考资料。

使用 msal2/SPA 应用程序注册时是否也需要进行这些更改(在 HttpClient 和 use_impersonation 范围内)?

谢谢

如果想在Blazor webassembly客户端中调用Azure AD投射的Azure函数,请参考以下步骤 如果要在angular应用中调用Azure AD投射的Azure功能,请参考以下代码

  • 创建Azure AD应用保护功能

    1. 注册 Azure AD 应用程序。完成后,请复制 应用程序(客户端)ID目录(租户)ID

    2. 配置重定向 URI。 Select Web 并输入 <app-url>/.auth/login/aad/callback.

    3. 启用隐式授权流程

    4. 定义API范围并复制

    5. 创建客户端密钥。

  • 在您的应用服务应用程序中启用 Azure Active Directory

  • 在 Azure 函数中配置 CORS 策略

  • 创建客户端AD应用访问功能

    1. 注册申请
    2. 启用隐式授权流程
    3. 配置API权限。让您的客户端应用程序具有访问功能的权限
  • 代码

  1. 创建自定义 AuthorizationMessageHandler class
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;

public class CustomAuthorizationMessageHandler : AuthorizationMessageHandler
{
    public CustomAuthorizationMessageHandler(IAccessTokenProvider provider, 
        NavigationManager navigationManager)
        : base(provider, navigationManager)
    {
        ConfigureHandler(
            authorizedUrls: new[] { "<your function app url>" },
            scopes: new[] { "<the function app  API scope your define>" });
    }
}
  1. Program.cs中添加以下代码。
 public static async Task Main(string[] args)
        {
            var builder = WebAssemblyHostBuilder.CreateDefault(args);
            builder.RootComponents.Add<App>("app");
             // register CustomAuthorizationMessageHandler 
            builder.Services.AddScoped<CustomAuthorizationMessageHandler>();
            // configure httpclient
            // call the following code please add packageMicrosoft.Extensions.Http 3.1.0
            builder.Services.AddHttpClient("ServerAPI", client =>
              client.BaseAddress = new Uri("<your function app url>"))
                    .AddHttpMessageHandler<CustomAuthorizationMessageHandler>();
            // register the httpclient
            builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>()
             .CreateClient("ServerAPI"));
            // configure Azure AD auth
            builder.Services.AddMsalAuthentication(options =>
            {
                builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
                options.ProviderOptions.DefaultAccessTokenScopes.Add("<the function app  API scope your define>");


            });

            await builder.Build().RunAsync();
        }
  1. 调用API
@page "/fetchdata"
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@inject HttpClient Http

<h1>Call Azure Function</h1>

<p>This component demonstrates fetching data from the server.</p>

<p>Result: @forecasts</p>

<button class="btn btn-primary" @onclick="CallFun">Call Function</button>

@code {
    private string forecasts;

    protected async Task CallFun()
    {
        forecasts = await Http.GetStringAsync("api/http");
    }


}