ChatGPT解决这个技术问题 Extra ChatGPT

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

我想要做什么

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

我还有一个客户网站,我想让它使用该 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 的评论为我做的,谢谢!
我正在为同样的事情而苦苦挣扎。从昨天开始。我也试图使用我的自定义中间件来强制它。真让人头疼

M
Mauricio Gracia Gutierrez

因为你有一个非常简单的 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 的配置方法中,添加以下内容:

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”标头。因此,不允许访问源“localhost:3000”。响应的 HTTP 状态代码为 415。
当您注册 app.UseCors AFTER ``app.UseMvc()` 时,这不太可能起作用。中间件按照注册的顺序执行
在 app.UseMvc 之前使用 app.UseCors,在 Configure 方法中似乎有效。出于某种原因,顺序似乎确实很重要。
我必须启用 options.DisableHttpsRequirement(); 才能使所有这些工作。似乎 https cors 设置不适用。
@MindingData 为什么我需要在纯 WebAPI 项目中添加 UseMVC() ?是否有必要加载所有 MVC 内容才能使 CORS 正常工作?
M
Mohammed Osman

在 ConfigureServices 添加 services.AddCors();之前 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();
}

在 configure 方法中告诉 CORS 使用你刚刚创建的策略:

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

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


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

我创建了自己的适合我的中间件类,我认为 .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 代码中发出请求时,浏览器会自动添加此标头。
M
Mo D Genesis
    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 核心 3.1
F
FoggyDay

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

我终于通过将 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 => 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 的引用对我有用。我被困了好几天试图弄清楚这一点。谢谢!
很高兴它有帮助:)
T
Towhid

在我的情况下,根据 MindingData 的回答,只有 get 请求效果很好。对于其他类型的请求,您需要编写:

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

不要忘记添加 .AllowAnyHeader()


同意 Towhid 需要 AllowAnyHeader()。如果 HEADER 的请求缺少某些内容,它会让服务器接收 OPTIONS 请求。
.AllowAnyHeader() 为我做了这件事,我遇到了预检响应问题。
o
okan

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


c
ckr

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

// https://stackoverflow.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<CorsMiddleware>();
您可以替换那些 2 ligne : context.Response.StatusCode = (int)HttpStatusCode.OK;等待 context.Response.WriteAsync(string.Empty);用一个简单的:返回;
为了扩展您对@user8266077 答案的扩展:请注意,如果由于其他原因导致请求失败,则此中间件将引发异常并且不会设置标头。这意味着在前端,它仍然看起来像一个 CORS 问题,即使它完全不同。我通过捕获 await _next(context) 中的任何异常并在发生这种情况时手动设置状态代码和响应来绕过此问题。我还必须向 Access-Control-Allow-Headers 添加“授权”,以便在从需要授权的 react 发出请求时,预检请求才能正常工作。
H
H.Azizkhani

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

谢谢!唯一对我有用的解决方案!
S
Sainath

上述过程都没有帮助,然后我阅读了解决问题的 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.
a
amilamad

最简单的解决方案是添加

    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。


H
Hossein Narimani Rad

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

谢谢你的帮助。肯定是利用了一部分答案,综合大家的答案,最终找出解决方案
R
Riddik

我认为,如果您使用自己的 CORS 中间件,则需要通过检查源标头来确保它确实是 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 发送了请求。这拯救了我的一天! (或者至少我的上午;))
k
kjbetz

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


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

对我来说,解决方案是更正订单:

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

L
LeonardoX

对于.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 更多示例


A
Adrian

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

这对我有用,我最初为 Windows 身份验证设置了我的项目,但后来不得不将其更改为匿名,我正确配置了 CORS,但 launchSettings.json 中的这个设置是罪魁祸首,谢谢你发布这个!
A
Andrew

.NET 核心 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


T
Tseng

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

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

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


谢谢你的帮助。尝试了一个新的解决方案并播放了 json 被发送出去,在我对其进行字符串化并让它工作之后它就工作了
A
Andy

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

如果您尝试使用 ASP.NET 中间件记录响应标头,则“Access-Control-Allow-Origin”标头将永远不会出现,即使它存在。我不知道如何,但它似乎是在管道之外添加的(最后我不得不使用wireshark来查看它)。 .NET CORE 不会在响应中发送“Access-Control-Allow-Origin”,除非您的请求中有“Origin”标头。 Postman 不会自动设置,因此您需要自己添加。


L
Lnn

这是我的代码:)

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

R
René Bizelli de Oliveira

就我而言,我在 UserRouting 之前使用 UseCors 进行了修复。


当我从 dotnet core 2.2 升级到 3.1 时,我遇到了类似的情况。必须将 app.UseCors() 移到 app.UseRouting() 上方。这个答案为我指明了正确的方向。
G
Goal Man

这是使用顶级语句配置 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();

C
Cray

简单易行的方法。

安装包

Install-Package Microsoft.AspNetCore.Cors

将下面的代码放在 startup.cs 文件中

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


w
warrickh

使用自定义操作/控制器属性来设置 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 控制器/操作上:

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

M
Michał Szymański

在我的情况下,我的原始名称末尾的字符 / 导致了一个问题。

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

D
Dominik

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

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


c
carl

我在上面得到了 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。
B
Bonomi

Microsoft.AspNetCore.Cors

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

Enable OPTIONS header for CORS on .NET Core Web API


A
Arshath Shameer

这是我如何做到的。

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