如何在 ASP.net Core WebAPI 中启用 CORS

How to enable CORS in ASP.net Core WebAPI

我想做什么

我有一个后端 ASP.Net Core Web API 托管在 Azure 免费计划(源代码:https://github.com/killerrin/Portfolio-Backend)上。

我还有一个客户网站,我想使用它 API。客户端应用程序不会托管在 Azure 上,而是托管在 Github 页面或我有权访问的另一个 Web 托管服务上。因此,域名不会排队。

考虑到这一点,我需要在 Web API 端启用 CORS,但是我已经尝试了几个小时的几乎所有方法,但它拒绝工作。

我如何进行客户端设置 它只是一个用 React.js 编写的简单客户端。我在 Jquery 中通过 AJAX 调用 APIs。 React 网站有效,所以我知道不是这样。 Jquery API 调用如我在尝试 1 中确认的那样工作。下面是我如何调用

    var apiUrl = "http://andrewgodfroyportfolioapi.azurewebsites.net/api/Authentication";
    //alert(username + "|" + password + "|" + apiUrl);
    $.ajax({
        url: apiUrl,
        type: "POST",
        data: {
            username: username,
            password: password
        },
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (response) {
            var authenticatedUser = JSON.parse(response);
            //alert("Data Loaded: " + authenticatedUser);
            if (onComplete != null) {
                onComplete(authenticatedUser);
            }
        },
        error: function (xhr, status, error) {
            //alert(xhr.responseText);
            if (onComplete != null) {
                onComplete(xhr.responseText);
            }
        }
    });

我试过的


尝试 1 - 'proper' 方式

https://docs.microsoft.com/en-us/aspnet/core/security/cors

我已经按照 Microsoft 网站上的这个教程进行了 T,尝试了在 Startup.cs 中全局启用它的所有 3 个选项,在每个控制器上设置它并在每个操作上尝试它。

按照此方法,跨域工作,但仅在单个控制器(POST 到 AccountController)上的单个操作上起作用。对于其他所有内容,Microsoft.AspNetCore.Cors 中间件拒绝设置 headers.

我通过NUGET安装了Microsoft.AspNetCore.Cors,版本是1.1.2

这是我在 Startup.cs

中的设置方式
    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        // Add Cors
        services.AddCors(o => o.AddPolicy("MyPolicy", builder =>
        {
            builder.AllowAnyOrigin()
                   .AllowAnyMethod()
                   .AllowAnyHeader();
        }));

        // Add framework services.
        services.AddMvc();
        services.Configure<MvcOptions>(options =>
        {
            options.Filters.Add(new CorsAuthorizationFilterFactory("MyPolicy"));
        });

        ...
        ...
        ...
    }

    // This method gets called by the runtime. Use this method to configure 
    //the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env,
    ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();

        // Enable Cors
        app.UseCors("MyPolicy");

        //app.UseMvcWithDefaultRoute();
        app.UseMvc();

        ...
        ...
        ...
    }

如你所见,我什么都照办。我两次都在 MVC 之前添加了 Cors,当这不起作用时,我尝试将 [EnableCors("MyPolicy")] 放在每个控制器上

[Route("api/[controller]")]
[EnableCors("MyPolicy")]
public class AdminController : Controller

尝试 2 - 暴力破解

https://andrewlock.net/adding-default-security-headers-in-asp-net-core/

在尝试上次尝试几个小时后,我想我会尝试通过尝试手动设置 headers 来暴力破解它,迫使它们在每次响应时都为 运行。我按照本教程执行此操作,了解如何手动将 headers 添加到每个响应。

这些是我添加的headers

.AddCustomHeader("Access-Control-Allow-Origin", "*")
.AddCustomHeader("Access-Control-Allow-Methods", "*")
.AddCustomHeader("Access-Control-Allow-Headers", "*")
.AddCustomHeader("Access-Control-Max-Age", "86400")

这些是其他的headers我试过但失败了

.AddCustomHeader("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE")
.AddCustomHeader("Access-Control-Allow-Headers", "content-type, accept, X-PINGOTHER")
.AddCustomHeader("Access-Control-Allow-Headers", "X-PINGOTHER, Host, User-Agent, Accept, Accept: application/json, application/json, Accept-Language, Accept-Encoding, Access-Control-Request-Method, Access-Control-Request-Headers, Origin, Connection, Content-Type, Content-Type: application/json, Authorization, Connection, Origin, Referer")

通过这种方法,Cross Site headers 得到了正确应用,它们出现在我的开发人员控制台和 Postman 中。然而,问题是当它通过 Access-Control-Allow-Origin 检查时,网络浏览器会发出嘶嘶声(我相信) Access-Control-Allow-Headers 说明 415 (Unsupported Media Type)

所以暴力破解也不行


终于

有没有人让这个工作,可以伸出援手,或者只是能够指出我正确的方向?


编辑

所以为了让 API 呼叫通过,我不得不停止使用 JQuery 并切换到纯 Javascript XMLHttpRequest 格式。

尝试 1

除了在 Configure 方法中将 app.UseCors 放在 app.UseMvc 之前,我按照 MindingData 的回答设法让 Microsoft.AspNetCore.Cors 工作。

此外,当与 Javascript API 解决方案 options.AllowAnyOrigin() 混合使用时,通配符支持也开始起作用。

尝试 2

所以我设法让尝试 2(暴力破解)起作用...唯一的例外是 Access-Control-Allow-Origin 的通配符不起作用,因此我必须手动设置域可以访问它。

它显然不理想,因为我只想让这个 WebAPI 对所有人开放,但它至少在一个单独的站点上对我有用,这意味着它是一个开始

app.UseSecurityHeadersMiddleware(new SecurityHeadersBuilder()
    .AddDefaultSecurePolicy()
    .AddCustomHeader("Access-Control-Allow-Origin", "http://localhost:3000")
    .AddCustomHeader("Access-Control-Allow-Methods", "OPTIONS, GET, POST, PUT, PATCH, DELETE")
    .AddCustomHeader("Access-Control-Allow-Headers", "X-PINGOTHER, Content-Type, Authorization"));

因为你有一个非常简单的 CORS 策略(允许来自 XXX 域的所有请求),你不需要把它弄得那么复杂。首先尝试执行以下操作(CORS 的一个非常基本的实现)。

如果您还没有,请安装 CORS nuget 包。

Install-Package Microsoft.AspNetCore.Cors

在 startup.cs 的 ConfigureServices 方法中,添加 CORS 服务。

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(); // Make sure you call this previous to AddMvc
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

然后在 startup.cs 的 Configure 方法中添加以下内容:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    // Make sure you call this before calling app.UseMvc()
    app.UseCors(
        options => options.WithOrigins("http://example.com").AllowAnyMethod()
    );

    app.UseMvc();
}

现在开始吧。策略适用于您希望针对不同操作(例如不同主机或不同 headers)使用不同策略的情况。对于您的简单示例,您真的不需要它。从这个简单的示例开始,然后根据需要进行调整。

进一步阅读:http://dotnetcoretutorials.com/2017/01/03/enabling-cors-asp-net-core/

根据您在 MindingData 的回答中的评论,它与您的 CORS 无关,它工作正常。

您的控制器操作return输入了错误的数据。 HttpCode 415 表示 "Unsupported Media type"。当您将错误的格式传递给控制器​​(即 XML 给只接受 json 的控制器)或者当您 return 错误的类型(return Xml 在声明为仅 return xml).

的控制器中

稍后检查您的操作是否存在[Produces("...")]属性

尝试在 Ajax 调用前添加 jQuery.support.cors = true;

也可能是您发送到 API 的数据不稳定,

尝试添加以下 JSON 函数

        var JSON = JSON || {};

    // implement JSON.stringify serialization
    JSON.stringify = JSON.stringify || function (obj) {

        var t = typeof (obj);
        if (t != "object" || obj === null) {

            // simple data type
            if (t == "string") obj = '"' + obj + '"';
            return String(obj);

        }
        else {

            // recurse array or object
            var n, v, json = [], arr = (obj && obj.constructor == Array);

            for (n in obj) {
                v = obj[n]; t = typeof (v);

                if (t == "string") v = '"' + v + '"';
                else if (t == "object" && v !== null) v = JSON.stringify(v);

                json.push((arr ? "" : '"' + n + '":') + String(v));
            }

            return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
        }
    };

    // implement JSON.parse de-serialization
    JSON.parse = JSON.parse || function (str) {
        if (str === "") str = '""';
        eval("var p=" + str + ";");
        return p;
    };

然后在您的数据中:对象将其更改为

    data: JSON.stringify({
        username: username,
        password: password
    }),
  • ConfigureServices 中添加 services.AddCors(); BEFORE services.AddMvc();

  • 配置中添加UseCors

     app.UseCors(builder => builder
         .AllowAnyOrigin()
         .AllowAnyMethod()
         .AllowAnyHeader());   
     app.UseMvc();
    

要点是在app.UseMvc().

前加上app.UseCors

确保在 MVC 之前声明 CORS 功能,以便中间件在 MVC 管道获得控制权并终止请求之前触发。

在上述方法生效后,您可以更改它配置一个特定的 ORIGIN 以接受 api 调用并避免让您的 API 对任何人开放

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(options => options.AddPolicy("ApiCorsPolicy", builder =>
    {
        builder.WithOrigins("http://localhost:4200").AllowAnyMethod().AllowAnyHeader();
    }));

    services.AddMvc();
}

在配置方法中告诉 CORS 使用您刚刚创建的策略:

app.UseCors("ApiCorsPolicy");
app.UseMvc();

我刚找到这篇关于这个主题的紧凑文章 - https://dzone.com/articles/cors-in-net-core-net-core-security-part-vi

我创建了自己的适用于我的中间件 class,我认为 .net 核心中间件有问题 class

public class CorsMiddleware
{
    private readonly RequestDelegate _next;

    public CorsMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public Task Invoke(HttpContext httpContext)
    {
        httpContext.Response.Headers.Add("Access-Control-Allow-Origin", "*");
        httpContext.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
        httpContext.Response.Headers.Add("Access-Control-Allow-Headers", "Content-Type, X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Date, X-Api-Version, X-File-Name");
        httpContext.Response.Headers.Add("Access-Control-Allow-Methods", "POST,GET,PUT,PATCH,DELETE,OPTIONS");
        return _next(httpContext);
    }
}

// Extension method used to add the middleware to the HTTP request pipeline.
public static class CorsMiddlewareExtensions
{
    public static IApplicationBuilder UseCorsMiddleware(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<CorsMiddleware>();
    }
}

并在 startup.cs

中以这种方式使用
app.UseCorsMiddleware();

在我的例子中,根据 MindingData 的回答,只有 get 请求运行良好。对于其他类型的请求,您需要写:

app.UseCors(corsPolicyBuilder =>
   corsPolicyBuilder.WithOrigins("http://localhost:3000")
  .AllowAnyMethod()
  .AllowAnyHeader()
);

别忘了加上.AllowAnyHeader()

在我的用例的 .NET Core 2.1 预览版中扩展 user8266077's , I found that I still needed to supply OPTIONS response for preflight requests

// 
public class CorsMiddleware
{
  private readonly RequestDelegate _next;

  public CorsMiddleware(RequestDelegate next)
  {
    _next = next;
  }

  public async Task Invoke(HttpContext context)
  {
    context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
    context.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
    // Added "Accept-Encoding" to this list
    context.Response.Headers.Add("Access-Control-Allow-Headers", "Content-Type, X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Accept-Encoding, Content-Length, Content-MD5, Date, X-Api-Version, X-File-Name");
    context.Response.Headers.Add("Access-Control-Allow-Methods", "POST,GET,PUT,PATCH,DELETE,OPTIONS");
    // New Code Starts here
    if (context.Request.Method == "OPTIONS")
    {
      context.Response.StatusCode = (int)HttpStatusCode.OK;
      await context.Response.WriteAsync(string.Empty);
    }
    // New Code Ends here

    await _next(context);
  }
}

然后像 Startup.cs

那样启用中间件
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
  app.UseMiddleware(typeof(CorsMiddleware));
  // ... other middleware inclusion such as ErrorHandling, Caching, etc
  app.UseMvc();
}

None 上述程序有帮助,然后我阅读 article 解决了问题。

下面是代码。

public void ConfigureServices(IServiceCollection services)
{
    // Add service and create Policy with options
    services.AddCors(options =>
    {
        options.AddPolicy("CorsPolicy",
            builder => builder.AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader()
            .AllowCredentials() );
    });


    services.AddMvc(); 
}

public void Configure(IApplicationBuilder app)
{
    // ...

    // global policy - assign here or on each controller
    app.UseCors("CorsPolicy");

并且在我的 actionmethod 之上

[EnableCors("CorsPolicy")]

我认为如果您使用自己的 CORS 中间件,您需要通过检查 [=13= 来确保它确实是 CORS 请求]来源header。

 public class CorsMiddleware
{
    private readonly RequestDelegate _next;
    private readonly IMemoryCache _cache;
    private readonly ILogger<CorsMiddleware> _logger;

    public CorsMiddleware(RequestDelegate next, IMemoryCache cache, ILogger<CorsMiddleware> logger)
    {
        _next = next;
        _cache = cache;
        _logger = logger;
    }
    public async Task InvokeAsync(HttpContext context, IAdministrationApi adminApi)
    {
        if (context.Request.Headers.ContainsKey(CorsConstants.Origin) || context.Request.Headers.ContainsKey("origin"))
        {
            if (!context.Request.Headers.TryGetValue(CorsConstants.Origin, out var origin))
            {
                context.Request.Headers.TryGetValue("origin", out origin);
            }

            bool isAllowed;
            // Getting origin from DB to check with one from request and save it in cache 
            var result = _cache.GetOrCreateAsync(origin, async cacheEntry => await adminApi.DoesExistAsync(origin));
            isAllowed = result.Result.Result;

            if (isAllowed)
            {
                context.Response.Headers.Add(CorsConstants.AccessControlAllowOrigin, origin);
                context.Response.Headers.Add(
                    CorsConstants.AccessControlAllowHeaders,
                    $"{HeaderNames.Authorization}, {HeaderNames.ContentType}, {HeaderNames.AcceptLanguage}, {HeaderNames.Accept}");
                context.Response.Headers.Add(CorsConstants.AccessControlAllowMethods, "POST, GET, PUT, PATCH, DELETE, OPTIONS");

                if (context.Request.Method == "OPTIONS")
                {
                    _logger.LogInformation("CORS with origin {Origin} was handled successfully", origin);
                    context.Response.StatusCode = (int)HttpStatusCode.NoContent;
                    return;
                }

                await _next(context);
            }
            else
            {
                if (context.Request.Method == "OPTIONS")
                {
                    _logger.LogInformation("Preflight CORS request with origin {Origin} was declined", origin);
                    context.Response.StatusCode = (int)HttpStatusCode.NoContent;
                    return;
                }

                _logger.LogInformation("Simple CORS request with origin {Origin} was declined", origin);
                context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
                return;
            }
        }

        await _next(context);
    }

对我来说,这与我使用的代码无关。对于 Azure,我们必须进入 App Service 的设置,在侧面菜单中输入 "CORS"。在那里我必须添加我从中请求内容的域。一旦我有了它,一切都变得神奇了。

我在上面找到了 MindingData 的答案,但我不得不使用 Microsoft.AspNet.Cors 而不是 Microsoft.AspNetCore.Cors。我在 Visual Studio 2019

中使用 .NetCore Web 应用程序 API 项目

最简单的解决方案是添加

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }

        app.UseCors(options => options.AllowAnyOrigin());

        app.UseHttpsRedirection();
        app.UseMvc();
    }

至Startup.cs。

在 launchSettings.json 中,在 iisSettings 下,将 anonymousAuthentication 设置为 true:

"iisSettings": {
    "windowsAuthentication": true,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:4200/",
      "sslPort": 0
    }
  }

然后,在 Startup.cs 的 ConfigureServices 下,services.AddMvc 之前,添加:

services.AddCors(options => options.AddPolicy("ApiCorsPolicy", builder =>
{
    builder
        .AllowAnyOrigin()
        .WithHeaders(HeaderNames.AccessControlAllowHeaders, "Content-Type")
        .AllowAnyMethod()
        .AllowCredentials();
}));

然后,在配置方法中,在 app.UseMvc() 之前添加:

app.UseCors("ApiCorsPolicy");

我为此苦苦挣扎了 DAYS。

我终于通过将 app.UseCors(CORS_POLICY); 移动到 Configure()TOP 来让它工作。

https://weblog.west-wind.com/posts/2016/sep/26/aspnet-core-and-cors-gotchas

Make sure you declare the CORS functionality before > MVC as the headers have to be applied before MVC completes the request.

<= Even though my app didn't call UseMVC(), moving UseCors() to the top fixed the problem

还有:

  • Microsoft.AspNetCore.Cors 曾经是 .Net Core 2 及更低版本中必需的 NuGet 包;它现在自动成为 .Net Core 3 及更高版本中 Microsoft.AspNetCore 的一部分。
  • builder.AllowAnyOrigin().AllowCredentials() CORS 选项现在在 .Net Core 3 及更高版本中是互斥的
  • CORS 策略似乎要求 Angular 使用 https 调用服务器。无论 .Net Core 服务器的 CORS 配置如何,http URL 似乎都会出现 CORS 错误。例如,http://localhost:52774/api/Contacts 会给出 CORS 错误;只需将 URL 更改为 https://localhost:44333/api/Contacts 即可。

补充说明

In my case, CORS wouldn't work until I moved app.UseCors() above app.UseEndpoints(endpoints => endpoints.MapControllers()).

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {      
       app.UseCors(builder => builder
                .AllowAnyHeader()
                .AllowAnyMethod()
                .SetIsOriginAllowed((host) => true)
                .AllowCredentials()
            );
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors();
    }

.NET 核心 3.1

为我工作以及文档说如何做:

在启动中 class:

readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins"; 

在 ConfigureServices() 方法中:

    services.AddCors(options =>
    {
        options.AddPolicy(MyAllowSpecificOrigins,
        builder =>
        {
            builder.WithOrigins("http://example.com",
                                "http://www.contoso.com");
        });
    });

在 Configure() 方法中:

    app.UseCors(MyAllowSpecificOrigins);  

https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-3.1

Microsoft.AspNetCore.Cors

将允许您使用内置功能执行 CORS,但它不处理 OPTIONS 请求。 迄今为止最好的解决方法是按照之前 post 中的建议创建一个新的中间件。检查以下标记为正确的答案 post:

简单易行的方法。

  1. 安装包

Install-Package Microsoft.AspNetCore.Cors

  1. 将下面的代码放入 startup.cs 文件

app.UseCors(options => options.AllowAnyOrigin());

我正在使用 .Net CORE 3.1,当我意识到我的代码已经开始实际工作但我的调试环境被破坏时,我花了很长时间用这个来撞墙,所以这里有 2 个提示,如果你'正在尝试解决问题:

  1. 如果您尝试使用 ASP.NET 中间件记录响应 header,"Access-Control-Allow-Origin" header 将永远不会出现,即使它是那里。不知道怎么弄的,好像是加在pipeline外的(最后不得不用wireshark才看到)

  2. .NET CORE 不会在响应中发送 "Access-Control-Allow-Origin",除非您的请求中包含 "Origin" header。 Postman 不会自动设置,所以你需要自己添加。

这是我的代码:)

  app.Use((ctx, next) =>
        {
            ctx.Response.Headers.Add("Access-Control-Allow-Origin", ctx.Request.Headers["Origin"]);
            ctx.Response.Headers.Add("Access-Control-Allow-Methods", "*");
            ctx.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
            ctx.Response.Headers.Add("Access-Control-Allow-Headers", "AccessToken,Content-Type");
            ctx.Response.Headers.Add("Access-Control-Expose-Headers", "*");
            if (ctx.Request.Method.ToLower() == "options")
            {
                ctx.Response.StatusCode = 204;

                return Task.CompletedTask;
            }
            return next();
        });

在我的例子中,我在 UserRouting 之前修复了 UseCors..

这是我的做法。

我看到在某些答案中,他们正在设置 app.UserCors("xxxPloicy") 并将 [EnableCors("xxxPloicy")] 放入控制器中。你不需要两者都做。

步骤如下。

在Startup.cs里面的ConfigureServices添加下面的代码。

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

如果想应用到整个项目那么在Startup.cs

的Configure方法中添加如下代码
app.UseCors("xxxPolicy");

如果你想将它添加到特定的控制器,然后添加启用 cors 代码,如下所示。

[EnableCors("xxxPolicy")]
[Route("api/[controller]")]
[ApiController]
public class TutorialController : ControllerBase {}

更多信息:see this

使用自定义 Action/Controller 属性设置 CORS headers。

示例:

public class AllowMyRequestsAttribute : ControllerAttribute, IActionFilter
{
    public void OnActionExecuted(ActionExecutedContext context)
    {
        // check origin
        var origin = context.HttpContext.Request.Headers["origin"].FirstOrDefault();
        if (origin == someValidOrigin)
        {
            context.HttpContext.Response.Headers.Add("Access-Control-Allow-Origin", origin);
            context.HttpContext.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
            context.HttpContext.Response.Headers.Add("Access-Control-Allow-Headers", "*");
            context.HttpContext.Response.Headers.Add("Access-Control-Allow-Methods", "*");
            // Add whatever CORS Headers you need.
        }
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        // empty
    }
}

然后在 Web 上 API 控制器/操作:

[ApiController]
[AllowMyRequests]
public class MyController : ApiController
{
    [HttpGet]
    public ActionResult<string> Get()
    {
        return "Hello World";
    }
}

如果您使用的是 app.UseHttpsRedirection(),并且您使用的不是 SSL 端口,请考虑在此处添加答案。

我使用 blazor webassembly 作为客户端,asp.net web api 核心作为后端,也有 cors 问题。

我用这些代码找到了解决方案:

我的 ASP.Net 核心网站 api Startup.cs ConfigureServices 和 Configure 方法的第一行如下所示:

public void ConfigureServices(IServiceCollection services)
{
   services.AddCors(options => options.AddPolicy("ApiCorsPolicy", builder =>
   {
        builder.WithOrigins("http://example.com").AllowAnyMethod().AllowAnyHeader();
    }));

 //other code below...
}

和我的配置方法:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseCors(
        options =>   options.WithOrigins("http://example.com").AllowAnyMethod().AllowAnyHeader()
            );
 //other code below...
}

http://example.com 更改为您的客户端域或 IP 地址

在我的案例中,原始名称末尾的字符 / 导致了问题。

在 .NET Core 3.1 中为我解决的解决方案:

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(c => c.AddPolicy("PolicyName", policy => {
        policy.WithOrigins("http://localhost:3000")
        .AllowAnyMethod()
        .AllowAnyHeader();
    }));
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseCors("PolicyName");
}

以下是适合我的设置:

在 ASP.NET Core 3.1 中对我有用的解决方案:

public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors(options =>
            {
                options.AddPolicy("CorsPolicy",
                    builder => builder.AllowAnyOrigin()
                    .AllowAnyMethod()
                    .AllowAnyHeader());
            });
            services.AddControllersWithViews();
        }

然后更改以下内容:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseCors("CorsPolicy");

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();
            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }

然后程序运行并解决了错误。

对于 .NET 核心 3.1

就我而言,我在添加 cors 中间件 之前使用了 https 重定向,并且能够通过更改它们的顺序来解决问题

我的意思是:

改变这个:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {

      ...
        
        app.UseHttpsRedirection();  

        app.UseCors(x => x
            .AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader());

      ...

     }

到这个:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {

      ...
        
        app.UseCors(x => x
            .AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader());

        app.UseHttpsRedirection(); 

      ...

     }

顺便说一句,允许来自任何来源和方法的请求在生产阶段可能不是一个好主意,您应该在生产阶段编写自己的 cors 策略。

for ASP.NET Core 3.1 这解决了我的问题 https://jasonwatmore.com/post/2020/05/20/aspnet-core-api-allow-cors-requests-from-any-origin-and-with-credentials

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();
            services.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.UseRouting();

            // global cors policy
            app.UseCors(x => x
                .AllowAnyMethod()
                .AllowAnyHeader()
                .SetIsOriginAllowed(origin => true) // allow any origin
                .AllowCredentials()); // allow credentials

            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(x => x.MapControllers());
        }
    }

对我来说,当我明确设置了我要发送的 header 后,它就开始工作了。我正在添加 content-type header,然后它起作用了。

.net

.WithHeaders("Authorization","Content-Type")

javascript:

this.fetchoptions = {
        method: 'GET', 
        cache: 'no-cache', 
        credentials: 'include', 
        headers: {
            'Content-Type': 'application/json',
        },
        redirect: 'follow', 
    }; 

AspNetCoreModuleV2 无法处理导致预检问题的选项

我发现 .net 核心模块不能很好地处理 OPTIONS,这造成了一个大的 CORS 问题:

解决方法:去掉星号*

在 web.config 中,从模块中排除 OPTIONS verb 因为 IIS 已经处理了这个动词 OPTIONSVerbHandler:

 <add name="aspNetCore" path="*" verb="* modules="AspNetCoreModuleV2" resourceType="Unspecified" />

用这个

<add name="aspNetCore" path="*" verb="GET,POST,PUT,DELETE" modules="AspNetCoreModuleV2" resourceType="Unspecified" />

对我来说,解决办法是更正订单:

app.UseCors();
app.UseAuthentication();
app.UseAuthorization();

这是一个 Program.cs 文件的 .NET 6 示例,它使用 top-level 语句来配置 CORS。可以看出,builder.Services.AddCors 和 app.UseCors 是必需的语句。两个带注释的 UseCors 语句也有效,并包含在内以显示其他选项。我没有对 ASP.NET API 控制器进行任何更改。

作为参考,我的开发 Angular 应用程序在 localhost:4200 上 运行 并且正在使用 https:// 连接到开发 ASP.NET API 服务器本地主机:7262.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddCors();
var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

//app.UseCors(options => options.WithOrigins("http://localhost:4200").AllowAnyMethod());
//app.UseCors(options => options.WithOrigins("http://localhost:4200").WithMethods(new string[] {"POST", "PUT"}));
app.UseCors(options => options.AllowAnyOrigin().AllowAnyMethod());

app.MapControllers();

app.Run();

.Net Core 6

var builder = WebApplication.CreateBuilder(args);
var apiCorsPolicy = "ApiCorsPolicy";

builder.Services.AddCors(options =>
{
    options.AddPolicy(name: apiCorsPolicy,
                      builder =>
                      {
                          builder.WithOrigins("http://localhost:4200", "https://localhost:4200")
                            .AllowAnyHeader()
                            .AllowAnyMethod()
                            .AllowCredentials();
                            //.WithMethods("OPTIONS", "GET");
                      });
});

builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();

var app = builder.Build();
app.UseHttpsRedirection();

app.UseCors(apiCorsPolicy);

app.UseAuthorization();
app.MapControllers();
app.Run();

here 更多示例