如何在ASP.net Core WebAPI中启用CORS [英] How to enable CORS in ASP.net Core WebAPI

查看:85
本文介绍了如何在ASP.net Core WebAPI中启用CORS的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要做什么

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

I have a backend ASP.Net Core Web API hosted on an Azure Free Plan (Source Code: https://github.com/killerrin/Portfolio-Backend).

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

I also have a Client Website which I want to make consume that API. The Client Application will not be hosted on Azure, but rather will be hosted on Github Pages or on another Web Hosting Service that I have access to. Because of this the domain names won't line up.

考虑到这一点,我需要在Web API端启用CORS,但是现在我已经尝试了几乎所有内容几个小时,并且它拒绝工作.

Looking into this, I need to enable CORS on the Web API side, however I have tried just about everything for several hours now and it is refusing to work.

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

How I have the Client Setup Its just a simple client written in React.js. I'm calling the APIs through AJAX in Jquery. The React site works so I know its not that. The Jquery API call works as I confirmed in Attempt 1. Here is how I make the calls

    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网站上的本教程操作,以T开头,尝试了在Startup.cs中全局启用它,在每个控制器上进行设置并在每个Action上进行尝试的所有3个选项.

I have followed this tutorial on the Microsoft Website to a T, trying all 3 options of enabling it Globally in the Startup.cs, Setting it up on every controller and Trying it on every Action.

遵循此方法,跨域可以工作,但只能在单个控制器上的单个Action上执行(POST到AccountController).对于其他所有内容,Microsoft.AspNetCore.Cors中间件都拒绝设置标头.

Following this method, the Cross Domain works, but only on a single Action on a single controller (POST to the AccountController). For everything else, the Microsoft.AspNetCore.Cors middleware refuses to set the headers.

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

I installed Microsoft.AspNetCore.Cors through NUGET and the version is 1.1.2

这是我在Startup.cs中设置的方式

Here is how I have it setup in 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")]放在每个控制器上

As you can see, I am doing everything as told. I add Cors before MVC both times, and when that didn't work I attempted putting [EnableCors("MyPolicy")] on every controller as so

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


尝试2-蛮力强制

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

在尝试了上一个尝试几个小时之后,我认为我会尝试通过手动设置标头,迫使它们在每个响应上运行来对它进行暴力破解.我在本教程之后进行了有关如何手动向每个响应添加标头的操作.

After several hours of trying on the previous attempt, I figured I would try to bruteforce it by trying to set the headers manually, forcing them to run on every response. I did this following this tutorial on how to manually add headers to every response.

这些是我添加的标题

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

这些是我尝试过的其他标头,

These are other headers I tried which failed

.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检查,但网络浏览器却对(c5)Access-Control-Allow-Headers声明了415 (Unsupported Media Type)

With this method, the Cross Site headers are being properly applied and they show up in my developer console and in Postman. The problem however is that while it passes the Access-Control-Allow-Origin check, the webbrowser throws a hissy fit on (I believe) Access-Control-Allow-Headers stating 415 (Unsupported Media Type)

所以蛮力方法也不起作用

So the brute force method doesn't work either

最后

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

Has anyone gotten this to work and could lend a hand, or just be able to point me in the right direction?

编辑

因此要使API调用通过,我不得不停止使用JQuery并切换为纯Javascript XMLHttpRequest格式.

So to get the API calls to go through, I had to stop using JQuery and switch to a Pure Javascript XMLHttpRequest format.

尝试1

通过遵循MindingData的答案,我设法使Microsoft.AspNetCore.Cors起作用,但在Configure方法中,除了app.UseCors放在app.UseMvc之前.

I managed to get the Microsoft.AspNetCore.Cors to work by following MindingData's answer, except within the Configure Method putting the app.UseCors before app.UseMvc.

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

In addition, when mixed with the Javascript API Solution options.AllowAnyOrigin() for wildcard support began to work as well.

尝试2

所以我设法使Attempt 2(强行强制执行)...唯一的例外是Access-Control-Allow-Origin的通配符不起作用,因此我必须手动设置有权访问的域它.

So I have managed to get Attempt 2 (brute forcing it) to work... with the only exception that the Wildcard for Access-Control-Allow-Origin doesn't work and as such I have to manually set the domains that have access to it.

这显然不是理想的,因为我只想向所有人开放此WebAPI,但是它至少在我自己的网站上对我有用,这意味着这是一个开始

Its obviously not ideal since I just want this WebAPI to be wide opened to everyone, but it atleast works for me on a separate site, which means it's a start

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的非常基本的实现).

Because you have a very simple CORS policy (Allow all requests from XXX domain), you don't need to make it so complicated. Try doing the following first (A very basic implementation of CORS).

如果尚未安装,请安装CORS nuget软件包.

If you haven't already, install the CORS nuget package.

Install-Package Microsoft.AspNetCore.Cors

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

In the ConfigureServices method of your startup.cs, add the CORS services.

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方法中,添加以下内容:

Then in your Configure method of your startup.cs, add the following :

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

现在试试吧.策略适用于您希望不同的策略用于不同的操作(例如,不同的主机或不同的标头)的情况.对于您的简单示例,您实际上不需要它.从这个简单的示例开始,然后根据需要进行调整.

Now give it a go. Policies are for when you want different policies for different actions (e.g. different hosts or different headers). For your simple example you really don't need it. Start with this simple example and tweak as you need to from there.

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

这篇关于如何在ASP.net Core WebAPI中启用CORS的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆