【问题标题】:JQuery stuck at CORS preflight and IIS ghost responseJQuery 卡在 CORS 预检和 IIS 鬼响应
【发布时间】:2013-01-31 13:52:48
【问题描述】:

我被卡住了。 说真的...... - 解决了。继续阅读:)

场景:我在这里尝试做正确的事情。我依靠 Thinktecture Identitymodel CORS DelegatingHandler 将 CORS 功能添加到了我的 REST 服务 (ASP.NET Web-API)。到目前为止一切顺利。

为了实际测试它是否有效,我做了以下操作:

  1. 我设置了一个简单的 HTML 页面并将其发布在与其他服务不同的主机上 (xttp://otherhost/simplewebpage)。该页面使用 JQuery 发出示例请求。代码见下文。
  2. 接下来,我将我的 rest 服务设置为不使用 iis express,而是使用它在我的开发机器上运行的完整实例 (xttp://developmenthost/restservice)。
  3. 最后但并非最不重要的是,在我的开发机器上,我打开 xttp://otherhost/simplewebpage 并触发 Ajax 请求。执行错误回调,告诉我 Chrome 中存在“传输错误”(IE9)或“”(空字符串)。我确保不存在与代理相关的连接问题或类似问题。

所以我开始查看 Fiddler 跟踪和 IIS 日志。 Fiddler 说没有 GET /rest/hello 请求,而是一个 OPTIONS /rest/hello 请求——这完全没问题,也是意料之中的!然而,对 OPTIONS 请求的响应相当有趣!

整个响应头如下所示:

HTTP/1.1 200 OK
Allow: OPTIONS, TRACE, GET, HEAD, POST
Server: Microsoft-IIS/7.5
Public: OPTIONS, TRACE, GET, HEAD, POST
Date: Fri, 15 Feb 2013 14:09:27 GMT
Content-Length: 0

这当然与预期的响应相差甚远。 有趣的是,我的应用程序中的请求甚至没有命中 Application_BeginRequest()。 所以我的应用程序无法对结果负责。我可以在我的 IIS 日志中看到该请求,并且 IIS 添加了 Powered-by-ASP.NET 标头。所以它肯定会通过(正确的)IIS 站点。

触发ajax请求的jQuery代码:

    function Run()
    {
        $.ajax({
            type: 'GET',
            url: url,
            dataType: "json",
            beforeSend: function(jqXhr) {
                jqXhr.setRequestHeader("Authorization", "Basic " + getBasicHttpEncodedString(userName, password));
                jqXhr.setRequestHeader("Api-Key", "123");
            },
            success: successCallback,
            error: errorCallback,
            timeout: 180*1000
        });
    }

生成的 OPTIONS 请求如下所示:

OPTIONS http://services.dev13/Rest/Hello HTTP/1.1
Host: developmenthost
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: http://otherhost/simplewebpage
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.57 Safari/537.17
Access-Control-Request-Headers: accept, origin, api-key, authorization
Accept: */*
DNT: 1
Referer: http://otherhost/simplewebpage
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

...你已经看到了上面的回复。

知道谁准确地回答了我的 OPTIONS 请求吗?还是我的 JQuery 代码有缺陷? 如果我使用 Postman(Google Chrome 应用程序)或者我在 Fiddler 中伪造请求(这可能是因为他们不进行 CORS 协商 - 没有 OPTIONS 请求),REST 服务就可以正常工作。

更新 #1: 今天早些时候,我在某处读到禁用 WebDAV 是强制性的,因为它会干扰 OPTIONS 请求。我的 IIS 角色服务视图告诉我 WebDAV 发布是未安装

* 更新 #2:* 问题解决了吗?我挖得更深了。在 IIS 中注册了一个模块,该模块负责对 OPTIONS 请求的“不想要的(?)”响应。它的名字是“OPTIONSVerbHandler”(处理程序:ProtocolSupportModule)。如果我禁用该模块,请求将传递到我的应用程序。创建一个更有意义的响应,然后随后是实际的 GET 请求! 耶!

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Server: Microsoft-IIS/7.5
Access-Control-Allow-Origin: http://otherhost/simplewebpage
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: accept,origin,api-key,authorization
X-AspNet-Version: 4.0.30319
Date: Fri, 15 Feb 2013 15:09:25 GMT
Content-Length: 0

一旦您知道问题出在哪里,您当然会发现大量资源告诉您确保您的 web.config 看起来像这样:-/

<system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <modules runAllManagedModulesForAllRequests="false">
      <remove name="WebDAVModule" />
    </modules>
    <handlers>
      <remove name="OPTIONSVerbHandler" />
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
  </system.webServer>

但它仍然不能在 IE9 中工作(“错误:无传输”)。万一有人和我走同样的路->这是IE9的事情:https://stackoverflow.com/a/10232313/1407618

【问题讨论】:

  • 尝试将 crossDomain 字段设置为 true..它对我有用
  • 你说“问题解决了?”它真的适合你吗?我有同样的问题,并尝试了所有这些解决方案,但仍然没有运气......我的问题stackoverflow.com/questions/22495240/…
  • @lapsus,我也遇到了类似的问题,如果你能帮忙请告诉我stackoverflow.com/questions/28213210/…
  • 我从来没有收到过使用 IIS 的预检请求,最终使用框架代替了 brrrr
  • 我正在应用这些修复,但它根本没有帮助。任何 HTTP OPTIONS 请求都无法通过,甚至 IIS 日志文件中都没有记录 OPTIONS 请求。经过 2 个小时的挫折,当我完全绝望时,我决定在 IIS 中重新启动 wcf 服务 Web 应用程序,它突然工作了!!据我所知,只要配置文件更改,IIS 就会重新启动应用程序池,但这次它没有重新启动。没关系,我只是想让它工作并完成。为此+1。希望这可以帮助某人..

标签: jquery http asp.net-web-api cors


【解决方案1】:

创建 PreflightRequestsHandler 类,您可以在其中允许请求标头 (1) 并在您的类之前启用 cors (2)。

1. public class PreflightRequestsHandler : DelegatingHandler
    {
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            if (request.Headers.Contains("Origin") && request.Method.Method.Equals("OPTIONS"))
            {
                var response = new HttpResponseMessage { StatusCode = HttpStatusCode.OK };
                // Define and add values to variables: origins, headers, methods (can be global)               
                response.Headers.Add("Access-Control-Allow-Origin", "*");
                response.Headers.Add("Access-Control-Allow-Headers", "content-type");
                response.Headers.Add("Access-Control-Allow-Methods", "*");
                var tsc = new TaskCompletionSource<HttpResponseMessage>();
                tsc.SetResult(response);
                return tsc.Task;
            }
            return base.SendAsync(request, cancellationToken);
        }

    }

2. [EnableCors(origins: "*", headers: "*", methods: "*", exposedHeaders: "X-Custom-Header")]

【讨论】:

    【解决方案2】:

    检查此set-access-control-allow-origin-in-web-api。这可能会对您有所帮助。

    【讨论】:

    • 问题是 IIS 正在拦截 OPTIONS 方法事务。该应用永远不会看到此流量,因此对应用进行任何更改都无济于事。
    【解决方案3】:

    你的答案在这里: https://gist.github.com/mathieucarbou/1114981

    基本上,IE 对 cors 有一些非常具体的警告和陷阱。我开始自己写一个,但后来我找到了 mathieucarbou 的解决方案,并认为他的解决方案更好。

    这可能是一个比您想要的更重的解决方案,但对于跨浏览器支持,我发现尽可能使用“自定义解决方案”来访问 IE 是可以接受的。

    【讨论】:

    • 需要明确的是,这只是一个关于 IE9 支持的答案,仅在问题的最后提及,并且仅在问题的主要部分得到解决之后才提到。
    猜你喜欢
    • 2018-03-15
    • 2021-11-12
    • 2019-10-21
    • 2017-08-01
    • 2020-09-05
    • 2021-03-14
    • 2016-12-19
    • 2020-02-21
    • 2019-08-10
    相关资源
    最近更新 更多