一尘不染

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

c#

我要做什么

我有一个在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站点可以正常工作,所以我不知道。正如我在尝试1中确认的那样,对Jquery
API的调用有效。这是我进行调用的方式

    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/zh-
cn/aspnet/core/security/cors

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

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

Microsoft.AspNetCore.Cors通过NUGET 安装,版本为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并切换为Pure Javascript XMLHttpRequest格式。

尝试1

我设法Microsoft.AspNetCore.Cors通过遵循MindingData的答案来工作,但在ConfigureMethod中放置了app.UseCorsbefore
app.UseMvc

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

尝试2

因此,我设法使Attempt 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"));

阅读 454

收藏
2020-05-19

共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/

2020-05-19