33

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

场景:我正在尝试在这里做正确的事情。我依靠 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 Publishing is Not installed

* 更新 #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

4

3 回答 3

2

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

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")]
于 2019-06-10T07:37:43.387 回答
1

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

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

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

于 2013-10-09T14:18:55.853 回答
0

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

于 2014-12-22T09:13:42.430 回答