NET5.0 Blazor WASM CORS 客户端异常

tom*_*rot 7 c# cors webapi blazor-webassembly

我有一个 Blazor WASM 应用程序和一个 Web Api,可以通过 HttpClient 由 Blzor 调用。这两个程序都运行在同一台机器上(并且也在生产环境中运行,这对于小型企业应用程序来说不应该是陌生的!)。

从 Blazor 客户端调用 Web Api 导致客户端 CORS 异常

从源“https://localhost:5001”获取“http://localhost:4040/”的访问已被 CORS 策略阻止:请求的资源上不存在“Access-Control-Allow-Origin”标头。如果不透明响应满足您的需求,请将请求的模式设置为“no-cors”以在禁用 CORS 的情况下获取资源。

这是这种情况下的预期行为。

在我用 PHP 开发的一个以前的 api 项目中,它具有相同的客户端行为,我可以通过简单地设置响应头来绕过 CORS 异常,例如

$response = new Response;
$response->setState(false, $route->command);
...
header("Access-Control-Allow-Origin: *");
echo $response;
Run Code Online (Sandbox Code Playgroud)

现在我想在我的 .net 5.0 Web Api 中使用它。我在互联网上找到了不同的文档来解决这个问题

https://docs.microsoft.com/de-de/aspnet/core/security/cors?view=aspnetcore-5.0 https://www.c-sharpcorner.com/article/enabling-cors-in-asp-net -core-api-application/ https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.cors.infrastructure.corspolicybuilder.withorigins?view=aspnetcore-5.0

并在我的 api 中实现它

    public class Startup {
        //---------------------------------------------------------------------

        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
        //---------------------------------------------------------------------

        public IConfiguration Configuration { get; }

        //---------------------------------------------------------------------

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices
                    (
                        IServiceCollection services
                    )
                    =>  services
                        .AddCors()
                        .AddSwaggerGen(c => c.SwaggerDoc("v1", new OpenApiInfo { Title = "api", Version = "v1"}) )
                        .AddControllers()
                        ;
        //---------------------------------------------------------------------

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure
                    (
                        IApplicationBuilder app,
                        IWebHostEnvironment env
                    )
                    =>  app.
                        apply( _ =>
                        {
                            if (true) //(env.IsDevelopment())
                            {
                                app
                                .UseDeveloperExceptionPage()
                                .UseSwagger()
                                .UseSwaggerUI( c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "api v1") );
                            }
                        })
                        .UseCors( cors =>
                            cors
                            .AllowAnyHeader()
                            .AllowAnyMethod()
                            .SetIsOriginAllowed( _ => true )
                            .AllowCredentials()
                        )
                        .UseHttpsRedirection()
                        .UseRouting()
                        .UseAuthorization()
                        .UseEndpoints( e => e.MapControllers() )
                        ;
        //---------------------------------------------------------------------
    }
Run Code Online (Sandbox Code Playgroud)

甚至尝试在 ApiController 中设置响应头

    [Route("/")]
    [ApiController]
    public sealed class ServertimeController : ControllerBase
    {
        //[EnableCors("AllowOrigin")]
        [HttpGet]
        public Servertime Get() {

            Response.Headers.Add("Access-Control-Allow-Origin", "*");
            Response.Headers.Add("Access-Control-Allow-Methods", "GET, POST, PUT");

            return servertime();
        }
    }
Run Code Online (Sandbox Code Playgroud)

Blazor WASM 客户端看起来像

    private async void onClick()
    {

        var response = await httpClient.GetFromJsonAsync<Servertime> ("http://localhost:4040");
        message = response.servertime;
        this.StateHasChanged();
    }
Run Code Online (Sandbox Code Playgroud)

但它仍然导致客户端 CORS 异常。为了绕过这个进行开发,我使用浏览器扩展“CORS Unblock”,但这不是部署的选项。

避免 Blazor 客户端异常的正确方法是什么,我错过了什么?

Dmi*_*kov 7

只需将其添加到ConfigureServices方法中:

services.AddCors(options =>
        {
            options.AddPolicy("DevCorsPolicy", builder =>
            {
                builder
                    .AllowAnyOrigin()
                    .AllowAnyMethod()
                    .AllowAnyHeader();
            });
        });
Run Code Online (Sandbox Code Playgroud)

这是配置方法:

app.UseCors("DevCorsPolicy");
Run Code Online (Sandbox Code Playgroud)

  • 禁用 CORS 相当于告诉某人禁用安全性以克服安全限制。一个非常糟糕的答案。特别是当正确的方法是使用 `WithOrigins()` 和允许的来源列表时,例如 `policy.WithOrigins("http://localhost:5000", "https://localhost:5001")` (3认同)
  • @PanagiotisKanavos 仅用于开发目的。这与生产部署无关。这个问题暗示了这一点。 (2认同)

Aay*_*Que 7

@Dmitriy Grebennikov 的回答也是有效的,但需要一些改进才能使其更安全。

ConfigureServicesofStartup.cs之前添加以下代码services.AddControllers();

services.AddCors(options =>
            {
                options.AddDefaultPolicy(builder => 
                builder.WithOrigins("https://localhost:44338")
                       .AllowAnyMethod()
                       .AllowAnyHeader());
            }); 
Run Code Online (Sandbox Code Playgroud)

确保您的网址不应以/.


您可以将许多 url 传递给WithOrigins方法。终于在Configure方法Startup.cs 前添加以下行app.UseAuthorization();app.UseRouting();

app.UseCors();
Run Code Online (Sandbox Code Playgroud)

代码现在应该可以工作了。