简体   繁体   English

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

[英]Enable preflight CORS between C# and Angular

I am trying to make CORS work for request that require a preflight check.我正在尝试使 CORS 为需要预检检查的请求工作。 In this case I am making a POST-request to the back-end with an extra header.在这种情况下,我使用额外的 header 向后端发出 POST 请求。

Angular: Angular:

  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: C# API:

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

Because of the preflight check it first makes an OPTIONS-request.由于预检检查,它首先发出一个 OPTIONS 请求。 When I do not define a separate options-endpoint in the backend I get a 405 Method Not Allowed.当我没有在后端定义单独的选项端点时,我得到一个 405 Method Not Allowed。 This made me think I needed a separate options-endpoint in my back-end on top of the post-endpoint.这让我觉得我需要一个单独的 options-endpoint 在我的后端在 post-endpoint 之上。

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

After adding this I run into a 415 Unsupported Media Type (on the options call).添加后,我遇到了 415 Unsupported Media Type(在选项调用中)。 This is probably because the Content-Type header is not supported for a HttpOptions request.这可能是因为 HttpOptions 请求不支持 Content-Type header。

I feel like the extra options endpoint shouldt be neccessary at all.我觉得根本不需要额外的选项端点。 The CORS-middleware I currently use is as follows:我目前使用的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");

Extra info: the CORS in general did already work.额外信息:CORS 通常已经工作了。 Cross-site scripting with a GET request and the Access-Control-Allow-Origin header went well.带有 GET 请求和 Access-Control-Allow-Origin header 的跨站点脚本运行良好。 It is just that I cannot get the POST/OPTIONS combo to work.只是我无法让 POST/OPTIONS 组合工作。

Edit: in the Startup.cs I first tried to use app.UseCors() as follows:编辑:在 Startup.cs 我首先尝试使用 app.UseCors() 如下:

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

This unfortuantely didnt work so then I resorted to inserting the middleware as described above.不幸的是,这不起作用,所以我求助于如上所述插入中间件。

Any help would be highly appreciated!任何帮助将不胜感激!

Make sure to call UseCors() before UseEndpoints().确保在 UseEndpoints() 之前调用 UseCors()。 Another hint: If you have credentials, the wildcard do not work as expected.另一个提示:如果您有凭据,则通配符不会按预期工作。 https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods

Ok, thanks a lot everybody.好的,非常感谢大家。 The problem was most likely in the middleware I was using.问题很可能出在我使用的中间件上。 This was a workaround I added because the UseCors() initially didnt work.这是我添加的一种解决方法,因为 UseCors() 最初不起作用。 This was probably because I didnt use app.AddCors() initially.这可能是因为我最初没有使用 app.AddCors()。 Without the custom middleware it makes everything a lot easier!如果没有自定义中间件,一切都会变得容易得多!

A quick look at the documentation will clarify few things.快速查看文档将澄清一些事情。 I share few extracts below我在下面分享一些摘录

Because of the preflight check it first makes an OPTIONS-request.由于预检检查,它首先发出一个 OPTIONS 请求。 When I do not define a separate options-endpoint in the backend I get a 405 Method Not Allowed.当我没有在后端定义单独的选项端点时,我得到一个 405 Method Not Allowed。 This made me think I needed a separate options-endpoint in my back-end on top of the post-endpoint.这让我觉得我需要一个单独的 options-endpoint 在我的后端在 post-endpoint 之上。

Preflight Request预检请求

For some CORS requests, the browser sends an additional OPTIONS request before making the actual request.对于某些 CORS 请求,浏览器会在发出实际请求之前发送一个额外的 OPTIONS 请求。 This request is called a preflight request.该请求称为预检请求。 The browser can skip the preflight request if all the following conditions are true如果以下所有条件都为真,浏览器可以跳过预检请求

  • The request method is GET, HEAD, or POST.请求方法是 GET、HEAD 或 POST。
  • The app doesn't set request headers other than Accept, Accept-Language, Content-Language, Content-Type, or Last-Event-ID.除了 Accept、Accept-Language、Content-Language、Content-Type 或 Last-Event-ID 之外,该应用不会设置请求标头。
  • The Content-Type header, if set, has one of the following values: application/x-www-form-urlencoded multipart/form-data text/plain Content-Type header(如果设置)具有以下值之一:application/x-www-form-urlencoded multipart/form-data text/plain

I feel like the extra options endpoint shouldt be neccessary at all.我觉得根本不需要额外的选项端点。

Except you are using CORS with endpoint routing, ASPNET Core should respond to appropriate preflight request when core is enabled on startup.除了使用带有端点路由的 CORS 外,ASPNET Core 应该在启动时启用内核时响应适当的预检请求。

Condition for Automatic preflight自动预检的条件

When the CORS policy is applied either:当应用 CORS 策略时:

  • Globally by calling app.UseCors in Startup.Configure.通过在 Startup.Configure 中调用 app.UseCors 来全局调用。
  • Using the [EnableCors] attribute.使用 [EnableCors] 属性。

ASP.NET Core responds to the preflight OPTIONS request. ASP.NET 内核响应预检选项请求。

Enabling CORS on a per-endpoint basis using RequireCors currently does not support automatic preflight requests.使用 RequireCors 在每个端点上启用 CORS 目前不支持自动预检请求。

Enable Cors on Starup在启动时启用 Cors

In configure service在配置服务中

 public void ConfigureServices(IServiceCollection services)
    {
        .
        //other codes
        .
    services.AddCors(options =>
        {
            options.AddDefaultPolicy(
                builder => //check corsbuilder for additonal config
                {
                    builder.WithOrigins("http://example.com",
                                        "http://www.contoso.com;
                });
        });
        .
        //other codes
        .
    }

and in Configure method并在配置方法中

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        .
        //Other codes
        .

        app.UseCors();

        .
        //Other codes
        .
    }

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

Enables Cors and make sure to AllowAnyHeader and AllowAnyMethod Using.Net Core启用 Cors 并确保 AllowAnyHeader 和 AllowAnyMethod Using.Net Core

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM