选项预检未在 jQuery 中处理

Posted

技术标签:

【中文标题】选项预检未在 jQuery 中处理【英文标题】:OPTIONS preflight not handled in jQuery 【发布时间】:2014-07-27 20:26:58 【问题描述】:

我在 localhost:63342 有一个网页,该网页中有一个 jQuery ajax 调用,连接到我在 localhost:55000 的 web 服务服务器。在网络服务中,我设置了 Access-Control 标头。

在Chrome的开发者工具的Network选项卡中,可以看到OPTIONS preflight的东西被发送了,响应头有以下内容,看起来不错。

Access-Control-Allow-Headers:x-requested-with, X-Auth-Token, Content-Type, Accept, Authorization
Access-Control-Allow-Methods:POST, OPTIONS, GET
Access-Control-Allow-Origin:*
Cache-Control:private
Content-Length:0
Date:Fri, 06 Jun 2014 13:30:58 GMT
Server:Microsoft-IIS/8.0

但是,对 OPTIONS 请求的响应遇到了我的 jQuery ajax 调用的错误函数。开发人员工具向我显示浏览器准备 POST,但失败了,因为它认为资源没有设置 Access-Control-Allow-Origin 标头。浏览器不会尝试发送 POST。以下是来自浏览器控制台的错误消息:

XMLHttpRequest cannot load http://localhost:55000/webservice/ws.svc/CreateOuting. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63342' is therefore not allowed access. 

好像 jQuery 正在干扰 OPTIONS,POST 过程。关于我应该做些什么来完成这项工作的任何想法?

这是我的 ajax 调用

    $.ajax(
        type: 'POST',
        data: JSON.stringify(obj),
        headers:  "Content-type": "application/json" ,
        url: base_url + 'CreateOuting',
        crossDomain: true,
        success: function (an_outing) 
                $('#listviewOutings').listview('refresh', true);
                $('#boxOutingName')[0].value = '';
                myLib.OpenBasicPopup('Success', 'The outing name was saved.')
        ,
        error: function (err) 
            alert(err.statusText); // response to OPTIONS request ends up here
        
    );

这是我如何在服务器上的方法中设置标头(.NET C#):

public bh_Outing CreateOuting(string strOuting) 
    try
    
        //for all cors requests  
        WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*");
        //identify preflight request and add extra headers  
         if (WebOperationContext.Current.IncomingRequest.Method == "OPTIONS")
          
            WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Methods", "POST, OPTIONS, GET");
            WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Headers", "x-requested-with, X-Auth-Token, Content-Type, Accept, Authorization");
            return null;
          

        // do stuff

这是该方法的接口。我认为它还不完美,但我也不认为它是问题所在。

[WebInvoke(UriTemplate = "*", Method = "*", ResponseFormat = WebMessageFormat.Json)]
[OperationContract]
bh_Outing CreateOuting(string strOuting);

感谢您查看此内容。我真的被困住了。

更新,2014 年 6 月 17 日下午 5:38 EST

我在我的 webconfig 中添加了一个元素,如 this post,这并没有改变我的结果。

【问题讨论】:

请求是什么样的?它是否包含某种身份验证凭据?如果是这样,您可能必须在预检响应中包含 Access-Control-Allow-Credentials 标头。见here 在服务器上设置Access-Control-Allow-Credentialslocalhost:50000 * 我的意思是Access-Control-Allow-Origin 标题当然。 感谢 user1429080 和 GuyT,但 1.) 没有涉及凭据,2.) 上面的第一个代码框显示 Access-Control-Allow-Origin 标头在响应 OPTIONS 请求时很好.问题是 POST 永远不会被发送。就像浏览器没有看到 OPTIONS 请求成功一样。还有什么想法吗? 你的 jQuery 版本是多少? 【参考方案1】:

这可能不是原因,但是您是否尝试过在 jQuery 中启用 cors?在任何 cors ajax 请求之前:

jQuery.support.cors = true;

【讨论】:

结果不变。不过还是谢谢。 好吧,既然服务器响应看起来不错,而您认为这是 jQuery 问题,我建议调试它 - 我的意思是在错误回调中放置一个断点,然后按照调用堆栈找出原因是什么.你已经试过了吗? 这不会启用 CORS。请在再次建议之前阅读documentation on jquery's site。 好吧,请原谅我的误解。我以前看过文档,谢谢。是的,它不启用 cors,但让 jQuery 认为 cors 是受支持的。奇怪的是,这有时有助于解决类似的问题,至少在旧版本上是这样。这就是为什么我特别指出,这可能不是原因。请就这个问题提出您的建议。 是的,Ilya 您的具体建议并没有解决问题,但是您的“按照调用堆栈找出问题”让我朝着正确的方向前进——尝试查看调用堆栈。【参考方案2】:

导致我发布上述问题的问题的原因似乎是 Chrome 错误地表示了实际发生的情况。正如我上面所写,发生的事情是:

... OPTIONS 请求的响应命中了我的错误函数 jQuery ajax 调用。开发人员工具向我显示浏览器已准备好 POST,但失败了,因为它认为资源没有 Access-Control-Allow-Origin 标头集。浏览器不尝试 发送 POST。

为了获得更多详细信息,我安装并使用了 Microsoft Message Analyzer。它表明正在发送 OPTIONS 请求;正在发送 OPTIONS 响应; POST 请求被发送回 web 服务 (!!!) 并发送 POST 响应。

这是一个巨大的突破,因为现在,我没有尝试解决 CORS 问题(Chrome 开发人员工具显示的错误消息),而是开始解决“未找到”和“错误请求”错误(错误MS 消息分析器显示的消息)。

我使用的另一个很有帮助的技术是我在我的网络服务中设置了跟踪。跟踪将内容写入日志文件,该文件默认在事件查看器中打开,并提供了我需要找出(真正的)问题的详细信息。这是我在 webconfig 中启用跟踪的内容。

  <system.diagnostics>
    <trace autoflush="true" />
    <sources>
      <source name="System.ServiceModel"
              switchValue="Critical, Error, Warning"
              propagateActivity="true">
        <listeners>
          <add name="myListener"
              type="System.Diagnostics.XmlWriterTraceListener"
              initializeData= "c:\logs\ServiceModelExceptions.svcLog" />
        </listeners>
      </source>
    </sources>
  </system.diagnostics>

我没有更改 CORS 设置(jQuery 和 web.config),现在它在 Chrome 中运行良好。另外,我在 www 上有 web 服务,所以它是真正的跨域,而不仅仅是 localhost:63342 到 localhost:55000。

【讨论】:

以上是关于选项预检未在 jQuery 中处理的主要内容,如果未能解决你的问题,请参考以下文章

预检响应中不允许使用方法选项

CORS withCredentials XHR 预检未在 Firefox 中发布 Cookie

处理后构建未在测试飞行中显示?

“相同域”上的角度选项 http 预检?

iframe 未在 Jquery 中加载

如何在 SiteMinder 受保护的环境中处理 CORS 预检请求?