簡體   English   中英

NET5.0 Blazor WASM CORS 客戶端異常

[英]NET5.0 Blazor WASM CORS client exception

我有一個 Blazor WASM 應用程序和一個 Web Api 由 Blzor 通過 HttpClient 調用。 這兩個程序都在同一台機器上運行(並且在生產環境中運行,這對於小型企業應用程序來說應該不會太奇怪。)。

從 Blazor 客戶端調用 Web Api 導致客戶端 CORS 異常

CORS 策略已阻止從來源“https://localhost:5001”訪問“http://localhost:4040/”:請求的資源上不存在“Access-Control-Allow-Origin”header。 如果不透明的響應滿足您的需求,請將請求的模式設置為“no-cors”以獲取禁用 CORS 的資源。

這是這種情況的預期行為。

在我在 PHP 開發的一個以前的 api 項目中,它具有相同的客戶端行為,我可以通過簡單地設置響應 header 例如繞過 CORS 異常

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

現在我想在我的 .net 5.0 Web Api 中使用它。我在 inte.net 中找到了不同的文檔來處理這個問題,就像在

https://learn.microsoft.com/de-de/as.net/core/security/cors?view=as.netcore-5.0 https://www.c-sharpcorner.com/article/enabling-cors-in -asp.net-core-api-application/ https://learn.microsoft.com/en-us/do.net/api/microsoft.as.netcore.cors.infrastructure.corspolicybuilder.withorigins?view=as.netcore -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() )
                        ;
        //---------------------------------------------------------------------
    }

甚至嘗試在 ApiController 中設置 Response Header

    [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();
        }
    }

Blazor WASM 客戶端看起來像

    private async void onClick()
    {

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

但它仍然導致客戶端 CORS 異常。 為了繞過這個進行開發,我使用了瀏覽器擴展“CORS Unblock”,但這不是部署的選項。

避免 Blazor 客戶端異常的正確方法是什么,我錯過了什么?

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

Startup.cs ConfigureServices ,在services.AddControllers();前添加如下代碼services.AddControllers();

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

確保您的網址不應以/結尾。


您可以將許多 url 傳遞給WithOrigins方法。 最后在Startup.csConfigure方法中,在app.UseAuthorization();之前添加以下行app.UseAuthorization(); app.UseRouting();

app.UseCors();

代碼現在應該可以工作了。

只需將此添加到 ConfigureServices 方法:

services.AddCors(options =>
        {
            options.AddPolicy("DevCorsPolicy", builder =>
            {
                builder
                    .AllowAnyOrigin()
                    .AllowAnyMethod()
                    .AllowAnyHeader();
            });
        });

這是配置方法:

app.UseCors("DevCorsPolicy");

對於Blazor WASM 中的解決方案,不在服務器端,此代碼片段

Microsoft.AspNetCore.Components.WebAssembly.Http.WebAssemblyHttpRequestMessageExtensions.SetBrowserRequestMode(
    httpRequestMessage, 
    Microsoft.AspNetCore.Components.WebAssembly.Http.BrowserRequestMode.NoCors
);

將告訴運行本地 PWA 的本地瀏覽器不要隨請求發送 CORS。

代碼示例(帶有調用和使用的命名空間)

HttpRequestMessage httpRequestMessage = new HttpRequestMessage{
    RequestUri = new Uri("[Adress]"),
    Content = new StringContent(),
    Method = HttpMethod.Post };

WebAssemblyHttpRequestMessageExtensions.SetBrowserRequestMode(httpRequestMessage, BrowserRequestMode.NoCors);

HttpResponseMessage response = client.SendAsync(httpRequestMessage).Result;

--> 來自“Dmitry Grebennikov”的版本有效。 在我的版本中,Post 不是異步的,PWA 會拋出錯誤。

var client = new HttpClient();

var request = new HttpRequestMessage
{
    Method = new HttpMethod("GET"),
    RequestUri = new Uri($"{site.BaseUrl}robots.txt")
};

request.Headers.Add("Accept", "text/plain");
request.SetBrowserRequestMode(BrowserRequestMode.NoCors);

var response = await client.SendAsync(request);

var txt = await response.Content.ReadAsStringAsync();

參考

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM