小编典典

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

all

我想要做什么

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

    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
个选项,在每个控制器上设置它并在每个操作上尝试它。

遵循此方法,跨域工作,但仅在单个控制器上的单个操作(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 并切换到纯 JavascriptXMLHttpRequest格式。

尝试 1

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

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

尝试 2

所以我设法让尝试 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"));

阅读 95

收藏
2022-04-27

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

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/

2022-04-27