即使在允许所有标头和来源之后,CORS政策也会出现问题

时间:2019-07-02 14:02:43

标签: c# .net-core cors signalr asp.net-core-signalr

我有一个dotnetcoreapp2.1,其中正在使用SignalR。我启用了所有源进行测试和所有标头,但出现以下错误:

  

..已被CORS政策阻止:对预检请求的响应   未通过访问控制检查:   响应中的“ Access-Control-Allow-Origin”标头不得为   当请求的凭据模式为“包括”时,使用通配符“ *”。的   XMLHttpRequest发起的请求的凭据模式为   由withCredentials属性控制。

我使用了以下配置:

public void ConfigureServices(IServiceCollection services)
        {

            services.AddCors(o => o.AddPolicy("MyCORSPolicy", builder =>
            {
                builder.AllowAnyOrigin()
                       .AllowAnyMethod()
                       .AllowCredentials() // DisallowCredentials doesn't work either
                       .AllowAnyHeader();
            }));

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

            services.AddSignalR();

        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {

            app.UseCors("MyCORSPolicy");

            app.UseHttpsRedirection();

            app.UseMvc();

            app.UseSignalR(routes =>
            {
                routes.MapHub<VehiclesHub>("/vehiclesHub");
            });

            app.UseWebSockets();

        }

现在,这里的问题是,当我尝试从react Web应用程序访问此Hub时出现此错误。但是,如果我从React native尝试使用

  

无法启动传输“ websockets” null

我什至在我的HUB或其他控制器上使用过

[EnableCors("MyCORSPolicy")]

此问题在所有Web api 2控制器上均发生,但现在我仅使用SignalR集线器失败。其他api端点工作正常。

编辑:

我的dotnetcore2.2应用程序托管在IIS服务器上。

1 个答案:

答案 0 :(得分:0)

好吧,在我看来,起源并不是问题,因为用户将使用其凭据访问数据。我进行了更多研究,表明CORS主要用于浏览器,在这些浏览器中,用户可以通过交叉源脚本注入和损害用户。

所以我在Github帖子上发现的解决方案是创建一个自定义中间件来解决此问题。由于我无法控制ASP.NET Core Signalr中使用的withCredentials,因此,最好的选择是使用中间件返回相同的来源:

public class CorsOverride
{
  private readonly RequestDelegate _next;

  public CorsOverride(RequestDelegate next)
  {
    _next = next;
  }

  public async Task Invoke(HttpContext httpContext)
  {
    const string allowOriginHeaderName = "Access-Control-Allow-Origin";
    if (httpContext.Response.Headers.ContainsKey(allowOriginHeaderName))
    {
      httpContext.Response.Headers.Remove(allowOriginHeaderName);
    }

    httpContext.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
    httpContext.Response.Headers.Add("Access-Control-Allow-Headers", "x-requested-with");

    if (httpContext.Request.Headers["Access-Control-Request-Method"].Count > 0)
    {
      foreach (var header in httpContext.Request.Headers["Access-Control-Request-Method"])
      {
        httpContext.Response.Headers.Add("Access-Control-Allow-Methods", header);
      }
    }
    else
    {
      httpContext.Response.Headers.Add("Access-Control-Allow-Methods", httpContext.Request.Method);
    }

    foreach (var origin in httpContext.Request.Headers.Where(h => h.Key == "Origin"))
    {
      httpContext.Response.Headers.Add(allowOriginHeaderName, origin.Value);
    }

    if (httpContext.Request.Method == "OPTIONS")
    {
      httpContext.Response.StatusCode = 200;
      await httpContext.Response.WriteAsync("");
    }
    else
    {
      await _next.Invoke(httpContext);
    }
  }
}

Original solution on my Github postMy article for CORS handling

如果有人对这种修复有异议,请在下面赞扬。