我在努力做什么

我有一个后台ASP。Net Core Web API托管在Azure免费计划上(源代码: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://learn.microsoft.com/en-us/aspnet/core/security/cors

我已经遵循微软网站上的本教程,尝试在Startup.cs中全局启用它的所有3个选项,在每个控制器上设置它,并在每个动作上尝试它。

按照这种方法,跨域工作,但只能在单个控制器上的单个动作上工作(POST到AccountController)。对于其他任何事情,Microsoft.AspNetCore.Cors中间件拒绝设置头文件。

我通过NUGET安装了Microsoft.AspNetCore.Cors,版本为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")

有了这个方法,跨站点的头被正确地应用,他们显示在我的开发控制台和邮差。然而,问题是,当它通过访问控制-允许起源检查时,web浏览器抛出了一个嘘声(我相信)访问控制-允许头部声明415(不支持的媒体类型)

所以暴力法也不管用


最后

有没有人得到了这个工作,可以伸出手来,或者只是能够指出我在正确的方向?


EDIT

因此,为了让API调用顺利进行,我不得不停止使用JQuery,转而使用纯Javascript的XMLHttpRequest格式。

尝试1

我设法让Microsoft.AspNetCore.Cors通过遵循MindingData的答案工作,除了在配置方法中将app.UseCors放在app.UseMvc之前。

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

尝试2

所以我已经设法让尝试2(暴力强迫它)工作…唯一的例外是,通配符访问控制-允许-起源不工作,因此我必须手动设置有权限访问它的域。

这显然不是理想的,因为我只是想让这个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"));

当前回答

对于。net CORE 3.1

在我的例子中,我在添加cors中间件之前使用了https重定向,并且能够通过改变它们的顺序来修复这个问题

我的意思是:

改变:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {

      ...
        
        app.UseHttpsRedirection();  

        app.UseCors(x => x
            .AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader());

      ...

     }

:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {

      ...
        
        app.UseCors(x => x
            .AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader());

        app.UseHttpsRedirection(); 

      ...

     }

顺便说一下,允许来自任何来源和方法的请求在生产阶段可能不是一个好主意,您应该在生产阶段编写自己的cors策略。

其他回答

如果CORS策略发生了,你可以看到inspect element => network…来处理这个问题,你可以把你的客户端应用URL或ip/port引入到。net core app中

var  MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddPolicy(name: MyAllowSpecificOrigins,
                      policy  =>
                      {
                          policy.WithOrigins("http://example.com",
                                              "http://www.contoso.com");
                      });
});

// services.AddResponseCaching();

builder.Services.AddControllers();

var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();

app.UseCors(MyAllowSpecificOrigins);

app.UseAuthorization();

app.MapControllers();

app.Run();

详情请浏览:https://learn.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-7.0

在我的情况下,只有得到请求工作良好,根据MindingData的答案。对于其他类型的请求,你需要写:

app.UseCors(corsPolicyBuilder =>
   corsPolicyBuilder.WithOrigins("http://localhost:3000")
  .AllowAnyMethod()
  .AllowAnyHeader()
);

不要忘记添加。allowanyheader ()

我是这样做的。

我看到在一些答案中,他们正在设置app.UserCors(“xxxPloicy”),并在控制器中放置[EnableCors(“xxxPloicy”)]。你不需要同时做两件事。

以下是步骤。

在ConfigureServices的Startup.cs中添加以下代码。

    services.AddCors(c=>c.AddPolicy("xxxPolicy",builder => {
        builder.AllowAnyOrigin()
        .AllowAnyMethod()
        .AllowAnyHeader();
    }));

如果你想在整个项目中应用,那么在Startup.cs中的Configure方法中添加以下代码

app.UseCors("xxxPolicy");

Or

如果你想把它添加到特定的控制器,然后添加enable cors代码,如下所示。

[EnableCors("xxxPolicy")]
[Route("api/[controller]")]
[ApiController]
public class TutorialController : ControllerBase {}

更多信息,请看这个

根据你在MindingData的回答中的评论,它与你的CORS无关,它工作得很好。

您的控制器操作返回错误的数据。HttpCode 415表示“不支持的媒体类型”。当你将错误的格式传递给控制器(即XML传递给只接受json的控制器)或当你返回错误的类型(在一个声明只返回XML的控制器中返回XML)时,就会发生这种情况。

为了以后检查操作上是否存在[Produces("…")]属性

简单易行的方法。

安装包

安装包Microsoft.AspNetCore.Cors

把下面的代码放在startup.cs文件中

app.UseCors(options => options. allowanyorigin ());