在 C# 和 Angular 之间启用预检 CORS

Posted

技术标签:

【中文标题】在 C# 和 Angular 之间启用预检 CORS【英文标题】:Enable preflight CORS between C# and Angular 【发布时间】:2020-07-25 08:00:27 【问题描述】:

我正在尝试使 CORS 适用于需要预检检查的请求。在这种情况下,我使用额外的标头向后端发出 POST 请求。

角度:

  let myHeaders = new HttpHeaders();
    myHeaders = myHeaders.append('Content-Type', 'application/json');
    return this.http.post<UserOrder>(`$this.apiURL/Order/PlaceOrder`, JSON.stringify(payload), headers : myHeaders);   //email); 

C# API:

[HttpPost("PlaceOrder")]
        public GenericResponse PlaceOrder(UserOrderInsertModel userOrder) 
        
            return _orderProvider.PlaceOrder(new UserOrder());
        

由于预检检查,它首先发出一个 OPTIONS 请求。当我没有在后端定义单独的选项端点时,我得到一个 405 Method Not Allowed。这让我觉得我需要一个单独的 options-endpoint 在我的后端在 post-endpoint 之上。

[HttpOptions("PlaceOrder")]
        public ActionResult PlaceOrderOptions(UserOrderInsertModel userOrder)
        
            return Ok();
        

添加此内容后,我遇到了 415 Unsupported Media Type(在选项调用中)。这可能是因为 HttpOptions 请求不支持 Content-Type 标头。

我觉得根本不需要额外的选项端点。我目前使用的CORS-middleware如下:

httpContext.Response.Headers.Add("Access-Control-Allow-Origin", "http://localhost:4200");
httpContext.Response.Headers.Add("Access-Control-Allow-Methods", "GET, POST, OPTIONS");  
httpContext.Response.Headers.Add("Access-Control-Allow-Headers", "*");
httpContext.Response.Headers.Add("Access-Control-Allow-Credentials", "true");

额外信息:一般来说,CORS 已经工作了。带有 GET 请求和 Access-Control-Allow-Origin 标头的跨站点脚本运行良好。只是我无法让 POST/OPTIONS 组合起作用。

编辑:在 Startup.cs 我首先尝试使用 app.UseCors() 如下:

app.UseCors();
    options => options.WithOrigins("http://localhost").AllowAnyMethod()
);

不幸的是,这不起作用,所以我求助于如上所述插入中间件。

任何帮助将不胜感激!

【问题讨论】:

您使用的是 .Net Core 还是 .Net Framework(以及哪个版本)? 我使用的是 .NET Core 3.0 你能在中间件中设置它吗,使用.addCors.useCors docs.microsoft.com/en-us/aspnet/core/security/… ? 预检请求应由 Web 服务器(反向代理)处理。例如,IIS 必须使用 CORS 模块,docs.microsoft.com/en-us/iis/extensions/cors-module/… 只是好奇,为什么这个问题被否决了? 【参考方案1】:

启用 Cors 并确保 AllowAnyHeader 和 AllowAnyMethod 使用 .Net Core

  services.AddCors(options =>
        
            options.AddDefaultPolicy(builder =>
                
                    builder.WithOrigins(Configuration.GetValue<string>("JwtConfig:corsWhiteListUrl"))
                        .AllowAnyHeader()
                        .AllowAnyMethod();
                );
        );

【讨论】:

【参考方案2】:

快速浏览一下文档会澄清一些事情。我在下面分享一些摘录

由于预检检查,它首先发出一个 OPTIONS 请求。当我没有在后端定义单独的选项端点时,我得到一个 405 Method Not Allowed。这让我觉得我需要一个单独的 options-endpoint 在我的后端在 post-endpoint 之上。

预检请求

对于某些 CORS 请求,浏览器会在发出实际请求之前发送一个额外的 OPTIONS 请求。该请求称为预检请求。 如果满足以下所有条件,浏览器可以跳过预检请求

请求方法是 GET、HEAD 或 POST。 应用程序没有设置除接受以外的请求标头, Accept-Language、Content-Language、Content-Type 或 Last-Event-ID。 Content-Type 标头(如果已设置)具有以下值之一: application/x-www-form-urlencoded multipart/form-data text/plain

我觉得根本不需要额外的选项端点。

除了您将 CORS 与端点路由一起使用外,ASPNET Core 应在启动时启用核心时响应适当的预检请求。

自动预检的条件

当应用 CORS 政策时:

通过在 Startup.Configure 中调用 app.UseCors 全局。 使用 [EnableCors] 属性。

ASP.NET Core 响应预检 选项请求。

使用 RequireCors 为每个端点启用 CORS 目前不支持自动预检请求。

在启动时启用 Cors

在配置服务中

公共无效配置服务(IServiceCollection 服务) . //其他代码 . services.AddCors(选项 => options.AddDefaultPolicy( builder => //检查 corsbuilder 的附加配置 builder.WithOrigins("http://example.com", “http://www.contoso.com; ); ); . //其他代码 .

在配置方法中

公共无效配置(IApplicationBuilder 应用程序,IWebHostEnvironment env) . //其他代码 . 应用程序.UseCors(); . //其他代码 .

此处为 3.0 https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-3.0#ecors 的完整文档

【讨论】:

【参考方案3】:

好的,非常感谢大家。问题很可能出在我使用的中间件上。这是我添加的一种解决方法,因为 UseCors() 最初不起作用。这可能是因为我最初没有使用 app.AddCors()。如果没有自定义中间件,一切都会变得容易得多!

【讨论】:

【参考方案4】:

确保在 UseEndpoints() 之前调用 UseCors()。 另一个提示:如果您有凭据,则通配符不会按预期工作。 https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods

【讨论】:

以上是关于在 C# 和 Angular 之间启用预检 CORS的主要内容,如果未能解决你的问题,请参考以下文章

在启动中启用 CORS 失败并出现预检错误

Angular 6 - 对预检请求的响应未通过访问控制检查:没有“Access-Control-Allow-Origin”标头

Angular $http.delete CORS 错误(预检请求)

带有 Windows 身份验证预检问题的 Angular 4 HTTP POST [重复]

对预检的响应:尽管启用了 CORS,但“没有 'Access-Control-Allowed-Origin'”

如何使用 Angular 7 在 django1.1 中启用 cors?