Ajax Web 服务调用 - 不存在“Access-Control-Allow-Origin”标头

Posted

技术标签:

【中文标题】Ajax Web 服务调用 - 不存在“Access-Control-Allow-Origin”标头【英文标题】:Ajax Web Service Call - No 'Access-Control-Allow-Origin' header is present 【发布时间】:2015-07-17 14:30:25 【问题描述】:

嘿嘿,

我知道以前有人问过这个问题,并且我已经阅读了这里每个问题的每一个答案,但似乎仍然无法让我的项目正常工作。不过,我的情况与其他问题有点不同,不确定这是否有什么不同,但我们开始吧。

我有一个由 Web 服务组成的项目。仅服务就可以正常工作,这没有问题。还有另一个项目处理 UI 部分并通过 jquery ajax 调用这些服务。它一直运行良好,因为我之前没有在 Google Chrome 上测试过这个案例。一切都可以在 Internet Explorer 上完美运行。

现在;我的 Web 服务应用程序在端口 40000 (localhost:40000) 上运行,UI 项目在其他一些随机端口上运行,但仍在 localhost 中。就像我说的,我的 ajax 调用等在 Internet Explorer 上运行良好,但在 Google Chrome 上却失败了。控制台显示以下错误:

XMLHttpRequest cannot load http://127.0.0.1:40000/abc.asmx/TheMethodName. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:17256' is therefore not allowed access. The response had HTTP status code 400.

顺便说一句,之前好像是“localhost:40000”,所以网上有帖子建议我应该把它改成IP地址而不是localhost。

无论如何,我还在我的网络服务项目中编辑了我的 web.config 文件并添加了以下内容(这没有任何意义)

<system.serviceModel>
  <bindings>
    <webHttpBinding>
      <binding name="crossDomain" crossDomainScriptAccessEnabled="true">
      </binding>
    </webHttpBinding>
  </bindings>

  <behaviors>

    <serviceBehaviors>
      <behavior>
        <serviceMetadata httpGetEnabled="true" />
        <serviceDebug includeExceptionDetailInFaults="false" />
      </behavior>
    </serviceBehaviors>

  </behaviors>

  <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>


<system.webServer>
  <modules runAllManagedModulesForAllRequests="true" />
  <httpProtocol>
    <customHeaders>
      <add name="Access-Control-Allow-Origin" value="http://localhost:17256" />
      <add name="Access-Control-Allow-Origin" value="*" />
      <add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS" />
      <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />
      <add name="Access-Control-Max-Age" value="1728000" />

    </customHeaders>
  </httpProtocol>
</system.webServer>

顺便说一句,如果我使用第一行:它完全失败并说响应头消息不匹配,我什至无法启动服务调用。

是的,我还编辑了我的 ajax 调用,添加了以下参数:

crossDomain: true,

现在,我在这里缺少什么?我已经为此工作了好几天,我快要失去理智了:) 改变项目的整个结构(服务 - 我的意思是 UI 样式)有点太晚了,因为已经将大量代码写入服务和用户界面项目。请帮助我很绝望! :)

干杯


编辑:

所以事实证明我需要使用 JSONP,而不是 JSON——因为它不会被访问控制所困,这很好。我可以将我的 ajax 调用转换为 JSONP 调用。但我需要另一个帮助:)

我已经编写了一个全局 ajax 方法,该方法从单独页面上的每个操作中调用,它的工作原理就像魅力一样(当然又是在 Internet Explorer 上)。现在我应该怎么做才能将此包装函数转换为 jsonp 东西?

function RemoteCall(WebService, RemoteMethod, RemoteParameters, callbackResult) 

if (RemoteParameters == null || RemoteParameters == "") 
    RemoteParameters = " ";


var remoteCall = $.ajax(
    type: "POST",
    url: ProvideService(WebService, RemoteMethod),
    data: RemoteParameters,
    contentType: ajaxContentType,
    dataType: ajaxDataType,
    async: true,
    crossDomain: true,
    success: function (msg) 
        msg.header("Access-Control-Allow-Origin", "*");
        callbackResult(msg.d);
    ,
    error: function (xhr, ajaxOptions, thrownError) 
        callbackResult(xhr.status + '\r\n' + thrownError + '\r\n' + xhr.responseText);
    
);

我看到一些帖子,我应该添加一个属性为 jsonp: 'jsonp_callback' 和回调方法(这是我感到困惑的地方)。这个呢?

另一件事;我一直在将我的 json 参数作为文本发送到像

这样的变量中
var jSONParams = ' UserID: "1", EmailAddress: "a@b.com" '; 

我应该继续以相同的格式发送它还是应该将其转换为某种 JSON 对象或其他东西?

顺便说一句:我的全局 ajax 函数位于一个完全独立的 JS 文件中 - 但不确定它是否有任何区别......

干杯

【问题讨论】:

端点是否使用任何类型的身份验证? Windows 身份验证等? 【参考方案1】:

我宁愿只启用 CORS 而不是更改所有 AJAX 调用。

您是否尝试修改 web 服务的 web.config 以添加以下行?

<system.webServer>
    <httpProtocol>
        <customHeaders>

            <add name="Access-Control-Allow-Origin" value="*" />
        </customHeaders>
    </httpProtocol>

还要检查这个问题,看看 CORS / JSONP 是否更适合您 So, JSONP or CORS?

【讨论】:

【参考方案2】:

解决 CORS 错误的关键是注意服务器响应中的标头。您需要下载像 Fiddler 这样的 http 流量监视器来检查这些标头。然后,您可以将它与浏览器控制台错误结合使用,以准确找出问题所在。

这是典型/成功的 200 OK CORS 响应的样子(直接取自 Fiddler):

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Vary: Accept-Encoding
Server: Microsoft-IIS/7.5
Access-Control-Allow-Origin: http://localhost:1234
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET,POST,OPTIONS
X-AspNet-Version: 4.0.30319
X-UA-Compatible: IE=edge
Persistent-Auth: false
WWW-Authenticate: Negotiate oYG2MIGzoAMKAQChCwYJKoZIgvcSAQIC...etc.
Date: Fri, 08 May 2015 01:14:37 GMT
Connection: close
Content-Length: 4711

...response body etc. etc. 

如果您获得 No 'Access-Control-Allow-Origin' header is present on the requested resource,标头要么从响应中丢失,要么以违反 Chrome 对 W3C 规范的实现的方式传递。

通过查看您的 web.config 文件,我愿意打赌它是后者。例如,这是一个包含多个条目的有效 Access Control Allow Origin 标头:

Access-Control-Allow-Origin: http://domain1.com,http://domain2.com

而您的 web.config 标头部分的配置方式将提供多个条目,这通常是无效的

Access-Control-Allow-Origin: http://localhost:17256
Access-Control-Allow-Origin: *

...尤其是在身份验证和 Access-Control-Allow-Credentials 标头被传递到安全端点的情况下:

【讨论】:

【参考方案3】:

欢迎来到浏览器领域不那么酷的 CORS 问题,我有以下建议:

    如果您可以将 Web 服务和 UI 部分托管在同一个端口上,创建一个项目并制作您的 Web 服务和 UI 子项目,那么这很容易解决这个问题。 如果您的 web 服务以 JSON 格式响应,请考虑使用 JSONP,最好为 web 服务提供 JSONP 支持。

希望对你有帮助

问候, 阿里夫·伊姆兰

【讨论】:

现在我有一个关于 JSONP 的问题,您可以在我原来的问题中看到 - 我已经编辑了它。有什么帮助吗? :) 哦,还有 PS:我不能在同一个端口上托管这些项目——这没有用,因为服务项目就像许多其他 UI 项目的提供者项目,我真的不想在同一个端口上运行所有 UI 项目 - 不确定它是否可能,因为在 IIS 中为每个端口创建了虚拟目录,并且怀疑 IIS 是否允许这样做......我想我会抓住 JSONP 的机会 - 如果我可以弄明白:) 看看这个json-jsonp-tutorial.craic.com/index.html,JSONP 对你来说并不是很难实现的东西。你能更具体地谈谈你面临的问题吗?【参考方案4】:

谢谢大家的回答;

我找到了解决问题的方法。好像我没有完全注意错误信息:)

在我将 Access-Control-Allow-Origin 标头添加到我的 web.config 文件中后,我发现我开始收到一些其他错误,即 content-type 自定义标头丢失,我认为我仍然收到 CORS 错误。

所以,在我的 web.config 中添加 &lt;add name="Access-Control-Allow-Origin" value="*" /&gt; 定义实际上首先解决了我的跨域问题!而且我还测试了以下 web.config 标头条目以允许来自端口的特定域或请求,它也像魅力一样工作 - 因为我认为这是最好的选择,因为我不会公开发布我的服务。

<add name="Access-Control-Allow-Origin" value="http://localhost:17256" />

祝大家好运,问题解决了:)

【讨论】:

您在 web.config 中添加了哪个标签?【参考方案5】:

在 web.config 文件中添加以下代码。

<system.webServer> 
<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
    <add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE,OPTIONS" />
    <add name="Access-Control-Allow-Headers" value="Content-Type" />
    <add name="Access-Control-Allow-Credentials" value="true" />
  </customHeaders>
</httpProtocol>

【讨论】:

以上是关于Ajax Web 服务调用 - 不存在“Access-Control-Allow-Origin”标头的主要内容,如果未能解决你的问题,请参考以下文章

使用 jquery ajax jsonp 调用 web 服务:错误

使用带有摘要身份验证、jquery ajax 调用的 RestFul PHP Web 服务

如何使用 ASP.NET C# 在使用 ajax 完成 Web 服务时生成警报

无法从 .net 中的 Ajax 调用 .asmx Web 服务

为啥从 ajax 调用 web 服务会引发内部服务器 500 错误?

JSONP详解