CORS + Windows 身份验证无法与 Edge 或 IE 配合使用

Posted

技术标签:

【中文标题】CORS + Windows 身份验证无法与 Edge 或 IE 配合使用【英文标题】:CORS + Windows Authentication not playing nice with Edge or IE 【发布时间】:2018-07-05 04:49:36 【问题描述】:

我遇到了仅在 Edge 和 IE11 中发生的 CORS 问题。 Chrome 运行良好。

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

目前,开发期间一切都在 localhost 上运行。

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

在此图中,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

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

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

【问题讨论】:

你用owin吗? @anılyıldırım 是的 @kettch 你解决了吗?我开始相信这是不可能的参考:social.technet.microsoft.com/Forums/windowsserver/en-US/… @IsaackRasmussen 抱歉,我被另一个优先事项分心了。我今天会回到这个问题,并仔细检查发布的答案。 【参考方案1】:

ASP.NET (OWIN)

Install-Package Microsoft.Owin.Cors

Startup.cs:

app.UseCors(CorsOptions.AllowAll)

网页配置:

<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>

【讨论】:

【参考方案2】:

您需要在 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。这样,如果您更改端口或其他任何内容,它仍然可以运行。

【讨论】:

我确保标题存在,但似乎并没有改变结果。

以上是关于CORS + Windows 身份验证无法与 Edge 或 IE 配合使用的主要内容,如果未能解决你的问题,请参考以下文章

CORS 预检请求返回带有 Windows 身份验证的 HTTP 401

带有 Windows 身份验证的 CORS

AngularJS + Asp.net WebApi - 由于 CORS,无法进行身份验证

Angular 7 .net 核心 2.2 WebApi Windows 身份验证 CORS

在 WCF 和 Windows 身份验证中处理 CORS

带有 Windows 身份验证的 Web api 中的 Cors 问题