即使在所有 headers 和来源被允许之后,CORS 政策制定问题

CORS policy making problems even after all headers and origins are allowed

我有一个 dotnetcoreapp2.1,我在其中使用 SignalR。我已启用所有来源进行测试和所有 headers 但我收到以下错误:

..has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

我使用的配置如下:

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 尝试它,我会得到

Failed to start the transport 'websockets' null

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

[EnableCors("MyCORSPolicy")]

此问题在所有网络 api 2 个控制器上都发生过,但现在我仅在 SignalR 集线器上失败。其他 api 个端点工作正常。

编辑:

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

嗯,在我的例子中,来源似乎不是问题,因为用户将使用他们的凭据访问数据。我进行了更多研究,发现 CORS 主要用于浏览器,在这些浏览器中,用户可能会被跨源脚本注入和伤害。

所以我在 Github post 上找到的解决方案是创建一个自定义中间件来解决这个问题。由于我无法控制 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);
    }
  }
}

My article for CORS handling

如有朋友对此类修复有异议,请在下方点赞。