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

Posted

技术标签:

【中文标题】如何在 ASP.net Core WebAPI 中启用 CORS【英文标题】:How to enable CORS in ASP.net Core WebAPI 【发布时间】:2021-12-30 09:59:00 【问题描述】:

我要做什么

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

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

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

我如何设置客户端 它只是一个用 React.js 编写的简单客户端。我在 Jquery 中通过 AJAX 调用 API。 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 - “正确”的方式

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

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

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

我通过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/

在尝试上一次尝试几个小时后,我想我会尝试通过手动设置标题来强制它,强制它们在每个响应上运行。我在本教程之后执行了此操作,该教程介绍了如何为每个响应手动添加标头。

这些是我添加的标题

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

这些是我尝试过的其他标头,但失败了

.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")

使用此方法,跨站点标头被正确应用,它们显示在我的开发者控制台和 Postman 中。然而问题是,当它通过Access-Control-Allow-Origin 检查时,网络浏览器会在(我相信)Access-Control-Allow-Headers 上抛出一个嘶嘶声,声明415 (Unsupported Media Type)

所以蛮力法也行不通


终于

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


编辑

为了让 API 调用通过,我不得不停止使用 JQuery 并切换到纯 javascript XMLHttpRequest 格式。

尝试 1

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

此外,当与用于通配符支持的 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"));

【问题讨论】:

对于您的415 (Unsupported Media Type) 问题,将Content-Type 请求标头设置为application/json 感谢您花时间写一个如此描述性的问题。 如果您使用 Postman 进行测试,请确保将请求标头的 Origin 设置为 * 或其他内容,然后尝试 #1 应该可以工作。没有这个头,Access-Control-Allow-Origin 将不会在响应头中返回。 下面关于 XMLHttpRequest 的评论帮我做了,谢谢! 我也在为同样的事情苦苦挣扎。从昨天开始。我也试图使用我的自定义中间件来强制它。真是头疼 【参考方案1】:

因为你有一个非常简单的 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();

现在试一试。策略适用于您需要针对不同操作(例如不同的主机或不同的标头)的不同策略。对于您的简单示例,您确实不需要它。从这个简单的示例开始,然后根据需要进行调整。

延伸阅读:http://dotnetcoretutorials.com/2017/01/03/enabling-cors-asp-net-core/

【讨论】:

XMLHttpRequest 无法加载 andrewgodfroyportfolioapi.azurewebsites.net/api/Authentication。对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,不允许访问 Origin 'localhost:3000'。响应的 HTTP 状态代码为 415。 当您注册 app.UseCors AFTER ``app.UseMvc()` 时,这不太可能起作用。中间件按照注册的顺序执行 在 app.UseMvc 之前使用 app.UseCors,在配置方法中似乎有效。出于某种原因,顺序似乎很重要。 我必须启用options.DisableHttpsRequirement(); 才能使这些功能正常工作。似乎 https cors 设置不适用。 @MindingData 为什么我需要在纯 WebAPI 项目中添加 UseMVC()?是否需要加载所有 MVC 内容才能使 CORS 正常工作??【参考方案2】:

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

【讨论】:

这对我有用。 codeproject.com/Articles/1150023/… 这确实应该得到更多的支持,作为一个好的“起点”。根据我超过 25 年的编码经验,知道如何打开闸门以确保它确实“工作”然后根据需要关闭/保护事情总是很高兴。 只是提到这一点,与Configure() 相比,ConfigureServices() 中的顺序并不重要 我使用了更多阅读器中的链接,这些步骤解决了这个错误。我不确定这些更改应该放在哪里(我认为是 API)。链接确认它们应该放在 API 中。谢谢您的帮助。我因这个错误而完全旋转。 仅供参考 - CORS 规范还指出,如果存在 Access-Control-Allow-Credentials 标头,则将来源设置为“*”(所有来源)无效。这意味着您不能像上面那样将AllowCredentials()AllowAnyOrigin() 一起使用。要使用AllowCredentials(),您需要设置WithOrigins()。 docs.microsoft.com/en-us/aspnet/core/security/…【参考方案3】:

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

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

【讨论】:

非常优雅的 Access-Control-Allow-Origin 运行方式。 这适用于 WebAPI 和 MVC 并且没有依赖关系,谢谢! 我也对此持怀疑态度,但它对我有用。我基本上尝试了所有其他方法来实现这一点,我可以在互联网上找到,但无论服务器如何响应访问标头。这很好用。我正在运行 aspnetcore 2.1。 只有当客户端在请求中发送标头“Origin”时,您才应该返回 cors 标头。在原始 CospMiddleware 中,它看起来像这样:if (!context.Request.Headers.ContainsKey(CorsConstants.Origin)) return this._next(context); 可能是“.net 核心中间件类有问题”,因为在使用 curl 或类似的东西测试它时,您只是不添加标题“Origin”。当您在 js 代码中发出请求时,浏览器会自动添加此标头。【参考方案4】:
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
          
       app.UseCors(builder => builder
                .AllowAnyHeader()
                .AllowAnyMethod()
                .SetIsOriginAllowed((host) => true)
                .AllowCredentials()
            );
    

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

【讨论】:

.SetIsOriginAllowed((host) => true) 为我解决了这个问题。 哇,所以我完全期望任何其他答案在这个只有 3 票的小家伙之前都能奏效。但我一丝不苟地尝试了每一个,......我一时兴起就去找你的,它奏效了。谢谢 这是在 .NET Core 3.1 上为我工作的那个,它允许几乎任何东西。 谢谢。这是唯一对我有用的解决方案。[code]services.AddCors();[/code] 的顺序也很重要。 这也是唯一对我有用的。 SignalR Asp.Net Core 3.1【参考方案5】:

我为此苦苦挣扎了好几天。

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

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

确保在 > MVC 之前声明 CORS 功能 必须在 MVC 完成请求之前应用标头。

UseMVC(),将 UseCors() 移到顶部也解决了问题

还有:

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 即可。

补充说明

在我的情况下,直到我将 app.UseCors() 移到 app.UseEndpoints(endpoints =&gt; endpoints.MapControllers()) 上方,CORS 才能工作。

【讨论】:

如果您使用的是Net Core 3,这个应该是答案。感谢您救了我的命! "使用端点路由,CORS 中间件必须配置为在对 UseRouting 和 UseEndpoints 的调用之间执行。不正确的配置将导致中间件停止正常运行。"这里docs.microsoft.com/en-us/aspnet/core/security/… "使用端点路由,CORS 中间件必须配置为在对 UseRouting 和 UseEndpoints 的调用之间执行。不正确的配置将导致中间件停止正常运行。"这里docs.microsoft.com/en-us/aspnet/core/security/… 您对使用 https URL 而不是 http 的引用对我有用。我被困了好几天试图弄清楚这一点。谢谢! 很高兴它有帮助:)【参考方案6】:

就我而言,根据 MindingData 的回答,只有 get 请求运行良好。对于其他类型的请求,您需要编写:

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

别忘了加.AllowAnyHeader()

【讨论】:

同意 Towhid 需要 AllowAnyHeader()。如果 HEADER 的请求缺少某些内容,它会让服务器接收 OPTIONS 请求。 .AllowAnyHeader() 为我做了,我的预检响应有问题。【参考方案7】:

对于 .NET CORE 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 策略。

【讨论】:

【参考方案8】:

为了扩展user8266077 的answer,我发现我仍然需要为我的用例在.NET Core 2.1-preview 中为preflight requests 提供OPTIONS 响应:

// https://***.com/a/45844400
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();

【讨论】:

我推荐这样添加中间件:app.Use&lt;CorsMiddleware&gt;(); 你可以替换那些 2 ligne : context.Response.StatusCode = (int)HttpStatusCode.OK;等待 context.Response.WriteAsync(string.Empty);用一个简单的:return; 扩展您对@user8266077 答案的扩展:请注意,如果由于其他原因请求失败,此中间件将抛出异常并且不会设置标头。这意味着在前端,即使它完全不同,它仍然看起来像一个 CORS 问题。我通过捕获await _next(context) 中的任何异常并在发生这种情况时手动设置状态代码和响应来绕过此问题。我还必须在 Access-Control-Allow-Headers 中添加“授权”,以便在从需要授权的 react 发出请求时,预检请求才能正常工作。【参考方案9】:

对于 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());
        
    

【讨论】:

谢谢!唯一对我有用的解决方案!【参考方案10】:

上述过程都没有帮助,然后我阅读了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");

在我的操作方法的顶部

[EnableCors("CorsPolicy")]

【讨论】:

这可能是个坏主意:您不应该在同一个应用程序中混合中间件 (app.UseCors()) 和 [EnableCors()]。您应该使用其中之一 - 但不能同时使用:docs.microsoft.com/en-us/aspnet/core/security/…:Use the [EnableCors] attribute or middleware, not both in the same app.【参考方案11】:

最简单的解决方案是添加

    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。

【讨论】:

【参考方案12】:

尝试在 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
    ),

【讨论】:

感谢您的帮助。肯定是利用了一部分答案,综合大家的答案,最终找出解决方案【参考方案13】:

我认为,如果您使用自己的 CORS 中间件,则需要通过检查 origin 标头来确保它确实是 CORS 请求。

 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);
    

【讨论】:

非常感谢。我几乎发疯了,问自己为什么Access-Control-Allow-Origin 标头不是由服务器发出的。实际上,我通过没有 Origin 标头的 Postman 发送了请求。这拯救了我的一天! (或者至少我的上午;))【参考方案14】:

对我来说,这与我使用的代码无关。对于 Azure,我们必须进入应用服务的设置,在侧面菜单中输入“CORS”。在那里我必须添加我从中请求内容的域。一旦我把它放进去,一切都是神奇的。

【讨论】:

哦,天哪 - 谢谢(.net 5/6) - 花了几天时间把我的头撞在这个上面。 Azure 似乎在应用服务中的 API 和网站上实现了自己的 CORS 功能。我在谷歌搜索时发现的任何文档中都没有提到这一点。如果您使用 Azure,请尝试一下!【参考方案15】:

在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();
));

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

app.UseCors("ApiCorsPolicy");

【讨论】:

这是为我做的,我最初为 Windows 身份验证设置了我的项目,但后来不得不将其更改为匿名,我正确配置了 CORS,但 launchSettings.json 中的这个设置是罪魁祸首,谢谢发布这个!。【参考方案16】:

.NET Core 3.1

为我工作以及文档如何做到这一点:

在启动类中:

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

【讨论】:

【参考方案17】:

对我来说,解决方案是更正顺序:

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

【讨论】:

【参考方案18】:

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

您的控制器操作返回了错误的数据。 HttpCode 415 表示“不支持的媒体类型”。当您将错误的格式传递给控制器​​(即 XML 到仅接受 json 的控制器)或返回错误的类型(在声明为仅返回 xml 的控制器中返回 Xml)时,就会发生这种情况。

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

【讨论】:

感谢您的帮助。尝试了一个新的解决方案并播放了 json 被发送出去,在我对其进行字符串化并让它工作后它工作了【参考方案19】:

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

    如果您尝试使用 ASP.NET 中间件记录响应标头,“Access-Control-Allow-Origin”标头将永远不会出现,即使它存在。不知道怎么弄的,好像是在管道外面加的(最后还是用wireshark看的)。

    .NET CORE 不会在响应中发送“Access-Control-Allow-Origin”,除非您的请求中有“Origin”标头。 Postman 不会自动设置,所以你需要自己添加。

【讨论】:

【参考方案20】:

这是我的代码:)

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

【讨论】:

【参考方案21】:

就我而言,我在 UserRouting 之前修复了 UseCors..

【讨论】:

我从 dotnet core 2.2 升级到 3.1 时遇到了类似的情况。必须将 app.UseCors() 移到 app.UseRouting() 上方。这个答案为我指明了正确的方向。【参考方案22】:

在我的情况下,我的原名末尾的字符 / 引起了问题。

在 .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");

【讨论】:

【参考方案23】:

在 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?");
            );
        

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

【讨论】:

【参考方案24】:

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

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

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

【讨论】:

【参考方案25】:

我在上面得到了 MindingData 的答案,但我必须使用 Microsoft.AspNet.Cors 而不是 Microsoft.AspNetCore.Cors。我在 Visual Studio 2019 中使用 .NetCore Web 应用程序 API 项目

【讨论】:

注意:您不应在 ASP.Net Cor 应用程序中使用 Microsoft.AspNet.Cors。如果您使用的是 .Net Core 3.0 或更高版本,则根本不需要为 CORS 导入任何 NuGet 包。如果您使用的是 .Net Core 2.3 或更低版本,则需要来自 NuGet 的适当版本的 Microsoft.AspNet.Cors。【参考方案26】:

Microsoft.AspNetCore.Cors

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

Enable OPTIONS header for CORS on .NET Core Web API

【讨论】:

【参考方案27】:

简单易行的方法。

    安装包

Install-Package Microsoft.AspNetCore.Cors

    把下面的代码放到startup.cs文件中

app.UseCors(options =&gt; options.AllowAnyOrigin());

【讨论】:

【参考方案28】:

我是这样做的。

我看到在某些答案中,他们设置了 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

【讨论】:

【参考方案29】:

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

例子:

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 Controller/Action 上:

[ApiController]
[AllowMyRequests]
public class MyController : ApiController

    [HttpGet]
    public ActionResult<string> Get()
    
        return "Hello World";
    

【讨论】:

【参考方案30】:

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

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

我的 ASP.Net 核心 web 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...

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

【讨论】:

以上是关于如何在 ASP.net Core WebAPI 中启用 CORS的主要内容,如果未能解决你的问题,请参考以下文章

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

选择 webApi 模板时如何将 ASP.Net 身份添加到 Asp.Net Core?

如何从 ASP.NET Core WebAPI 获取 int 值?

ASP.Net Core WebApi几种版本控制对比

如何在无视图 WebAPI ASP.NET Core 应用程序中使用 [Authorize] 和防伪?

ASP.NET Core WebApi返回结果统一包装实践