CORS + Windows身份验证与Edge或IE

时间:2018-01-25 20:27:00

标签: asp.net-mvc asp.net-web-api cors microsoft-edge

我的CORS问题只发生在Edge和IE11中。 Chrome工作正常。

我的设置是一个ASP.NET MVC5应用程序(客户端),它有一个脚本调用一个单独的ASP.NET MVC5应用程序(API),它只包含WebAPI控制器。两个应用程序中的安全性都是通过Windows身份验证。

目前,在开发过程中,一切都在localhost上运行。

当客户端脚本调用API时,OPTIONS预检工作正常。但是,当GET发生时,Edge和IE会出现以下错误:

enter image description here

在此图片中,localhost:50281是客户端,localhost:47205是API。

奇怪的是,呼叫实际上并没有击中控制器。控制器使用自定义AuthorizeAttribute进行修饰,并且其中的断点不会被击中。

以下是在API项目中设置CORS的方法:

的Global.asax.cs

protected void Application_BeginRequest()
{
    if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
    {
        Response.Headers.Add("Access-Control-Allow-Origin", "http://localhost:50281");
        // Yes, there are too many headers. I've been working on this a while, and there are a few overkill options that have crept in
        Response.Headers.Add("Access-Control-Allow-Headers", "X-AspNet-Version,X-Powered-By,Date,Server,Accept,Accept-Encoding,Accept-Language,Cache-Control,Connection,Content-Length,Content-Type,Host,Origin,Pragma,Referer,User-Agent");
        Response.Headers.Add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, HEAD, OPTIONS");
        Response.Headers.Add("Access-Control-Allow-Credentials", "true");
        Response.Headers.Add("Access-Control-Max-Age", "600");
        Response.End();
    }
}

WebApiConfig.cs

public static void Register(HttpConfiguration config)
{
    // Web API configuration and services
    var cors = new EnableCorsAttribute("http://localhost:50281", "*", "*");
    cors.SupportsCredentials = true;
    cors.PreflightMaxAge = 600;
    config.EnableCors(cors);
    // Web API routes
    config.MapHttpAttributeRoutes();

    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );
}

以下是客户端项目中的脚本函数:

GetStatus = () => {
    $.ajax({
        type: "GET",
        url: apiUrl,
        dataType: "json",
        crossDomain: true,
        xhrFields: {
            withCredentials: true
        },
        contentType: "application/json; charset=UTF-8",
        success: (result) => {
            this.Status(result);
        }
    });
}

更新

我修改了Global.asax.cs以确保每个请求都包含Access-Control-Allow-Origin和Access-Control-Allow-Credentials,如建议的那样。但是,这仍然只在Edge和IE中产生401。它在Chrome中运行良好。

更新2

我猜有些事情发生了变化。我错过了错误现在减少到以下内容: enter image description here

这显然是我得到适当的标题。但是,出于某种原因,尽管存在withCredentials: true,Edge和IE仍然不允许身份验证通过。我还缺少另一件吗?

2 个答案:

答案 0 :(得分:3)

ASP.NET(OWIN)

Install-Package Microsoft.Owin.Cors

Startup.cs:

app.UseCors(CorsOptions.AllowAll)

Web配置:

<system.webServer>
  <handlers>
    <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
    <remove name="OPTIONSVerbHandler" />
    <remove name="TRACEVerbHandler" />
    <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
  </handlers>
</system.webServer>

答案 1 :(得分:0)

您需要使用GET请求以及预检OPTIONS请求返回Access-Control-Allow-Origin(ACAO)和Access-Control-Allow-Credentials(ACAC)标头。对于您通过cookie /身份验证的每个跨域请求,都需要返回这两个标头。

最佳/最简单/最干净的方法是编码,以便对包含Origin请求标头的所有请求(OPTIONS,GET,POST等)添加ACAO和ACAC标头。然后,对于OPTIONS请求,添加其他Access-Control-Allow- *标头......

此外,对于FWIW,在ACAO标头中返回Origin请求标头的值是明智的想法,而不是将其硬编码为http://localhost:50281。这样,如果你改变你的端口或其他什么,它仍然会起作用。