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

查看:25
本文介绍了如何在 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 站点有效,所以我知道不是这样.Jquery API 调用如我在尝试 1 中所确认的那样工作.这是我进行调用的方法

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 网站上的本教程进行了操作,尝试了在 Startup.cs 中全局启用它的所有 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.

按照这种方法,跨域可以工作,但只能在单个控制器上的单个操作上工作(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 检查时,网络浏览器会在(我相信)Access-Control-Allow-Headers 上发出嘶嘶声声明 415(不支持的媒体类型)

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)

所以蛮力法也行不通

终于

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

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

所以我已经设法让尝试 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 的配置方法中,添加以下内容:

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天全站免登陆