【问题标题】:Blazor WebAssembly blocks WebApi AllowAnonymousBlazor WebAssembly 阻止 WebApi AllowAnonymous
【发布时间】:2020-09-04 09:31:03
【问题描述】:

我创建了一个 Blazor WebAssembly 项目,并希望为 WebAPI 提供一个公共可用功能。

[Route("api/[controller]")]
[ApiController]
[Authorize]
public class SystemEvalApiController : ControllerBase
{
    public SystemEvalApiController(AppDbContext context, IMapper mapper)
    {...}

    [Route("LatestEvals")]
    [AllowAnonymous]
    public ActionResult LatestEvals()

那是我的 Api 控制器,我应该可以调用它:

SystemEvalPublicViewModel = await Http
                .GetFromJsonAsync<SystemEvalPublicViewModel>(
                    HttpService.BuildUrl("api/SystemEvalApi/LatestEvals"));

当我没有登录任何帐户时。但是我得到了这个错误:

info: System.Net.Http.HttpClient.JPB.BorannRemapping.ServerAPI.LogicalHandler[100]
      Start processing HTTP request GET https://localhost:44330/api/SystemEvalApi/LatestEvals
blazor.webassembly.js:1 info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
      Authorization failed.

看起来“DefaultAuthorizationService”无法识别匿名属性,但我找不到直接失败的点。

如何声明无需登录即可从 HttpClient 访问的 WebAPI 函数。 Microsoft.AspNetCore.Components.WebAssembly.Server 3.2.0.-rc1.20223.4

编辑: 这是 ClientServices 的声明:

var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("app");

builder.Services.AddHttpClient("JPB.BorannRemapping.ServerAPI", client =>
    {
        client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress);
    })
    .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();

// Supply HttpClient instances that include access tokens when making requests to the server project
builder.Services.AddTransient(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("JPB.BorannRemapping.ServerAPI"));
builder.Services.AddTransient(e => new HttpService(e.GetService<HttpClient>()));
builder.Services.AddApiAuthorization();
builder.Services.AddBlazoredLocalStorage();

await builder.Build().RunAsync();

【问题讨论】:

  • 你能把你注册服务的代码和你的注入方式贴出来吗? Blazor 应用程序不知道您如何保护您的 api,它无法猜测存在允许匿名用户的方法。这就像你不是为应用编写的服务。
  • 我添加了 program.cs 内容。我通过正常的@inject 语法注入 HttpClient(或 HttpService,它只是一个包含常用方法的包装器)。

标签: c# asp.net-core blazor webassembly


【解决方案1】:

因此,每次您获得HttpClient 时,它都会使用BaseAddressAuthorizationMessageHandler 来尝试验证请求。但在这种情况下,您的请求不应被验证,因此您可以进行如下操作:

注册

builder.Services.AddHttpClient("JPB.BorannRemapping.ServerAPI.Anonymous", client =>
    {
        client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress);
    });

用法

@inject IHttpClientFactory _factory

@code {
...
     var httpClient = _factory.CreateClient("JPB.BorannRemapping.ServerAPI.Anonymous");
     var httpService = new HttpService(httpClient);
     SystemEvalPublicViewModel = await httpClient
                .GetFromJsonAsync<SystemEvalPublicViewModel>(
                    httpService.BuildUrl("api/SystemEvalApi/LatestEvals"));
}

【讨论】:

  • 一年半后这对我帮助很大,谢谢!
【解决方案2】:

基于来自火星的@agua 的答案。

在 Program.cs 中注册

您可以将 2 个名为 HttpClient 的服务集合添加到服务集合中(第一个用于经过身份验证的调用,第二个用于匿名调用):

builder.Services.AddHttpClient("YourProject.ServerAPI", 
        client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
                .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();
builder.Services.AddHttpClient("YourProject.ServerAPI.Anonymous", 
        client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress));

// Supply HttpClient instances that include access tokens when making requests to the server project
builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("YourProject.ServerAPI"));
//Register a new service for getting an Anonymous HttpClient
builder.Services.AddScoped<IHttpAnonymousClientFactory, HttpAnonymousClientFactory>();

为依赖注入添加新的接口和实现:

    public interface IHttpAnonymousClientFactory
    {
        HttpClient HttpClient { get; }
    }

    public class HttpAnonymousClientFactory : IHttpAnonymousClientFactory
    {
        private readonly IHttpClientFactory httpClientFactory;

        public HttpAnonymousClientFactory(IHttpClientFactory httpClientFactory)
        {
            this.httpClientFactory = httpClientFactory;
        }

        public HttpClient HttpClient => httpClientFactory.CreateClient("YourProject.ServerAPI.Anonymous");
    }

在 Razor 组件中的使用(用于匿名 HttpClient)

        [Inject]
        private IHttpAnonymousClientFactory httpAnonymousClientFactory { get; set; }

        private MyViewModel myModel;

        protected override async Task OnInitializedAsync()
        {
            myModel = await httpAnonymousClientFactory.HttpClient.GetFromJsonAsync<MyViewModel>($"api/mycontroller/myendpoint");
        }

在 Razor 组件中的使用(用于经过身份验证的 HttpClient)

        [Inject]
        private HttpClient httpClient { get; set; }

        private MyOtherViewModel myModel;

        protected override async Task OnInitializedAsync()
        {
            myModel = await httpClient.GetFromJsonAsync<MyOtherViewModel>($"api/mycontroller/mysecureendpoint");
        }

【讨论】:

    猜你喜欢
    • 2021-10-20
    • 2022-11-09
    • 2020-08-24
    • 1970-01-01
    • 2020-08-19
    • 2020-06-26
    • 2021-02-08
    • 2020-06-28
    • 2020-09-02
    相关资源
    最近更新 更多