【问题标题】:soap in ajax not workingajax中的肥皂不起作用
【发布时间】:2013-03-18 07:43:01
【问题描述】:

我正在尝试创建一个连接到此 Web 服务的基本 HTML 页面: http://wsf.cdyne.com/WeatherWS/Weather.asmx 经过数小时修补教程和代码示例后,我完全不知道为什么这不起作用。 (我的请求收到 404,或者根本没有状态..)这是扩展演示的一部分,该演示已经使用 Soap 连接到类似的 Web 服务,教授的示例与嗯..

我的代码如下:

xmlHttpObj.open("POST", "http://wsf.cdyne.com/WeatherWS/Weather.asmx", true);
xmlHttpObj.setRequestHeader("Content-Type", "text/xml");
xmlHttpObj.setRequestHeader("SOAPAction", "http://ws.cdyne.com/WeatherWS/GetCityForecastByZIP");

var envelope = '<?xml version="1.0" encoding="utf-8"?> \n' +
               '<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' +
               ' xmlns:xsd="http://www.w3.org/2001/XMLSchema"' +
               ' xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">' +
               '   <soap:Body> \n' +
               '       <GetCityForecastByZIP xmlns="http://ws.cdyne.com/WeatherWS/"> \n' +
               '           <ZIP>' + selectedZip + '</ZIP> \n' +
               '       </GetCityForecastByZIP> \n' +
               '   </soap:Body> \n' +
               '</soap:Envelope> ';

xmlHttpObj.onreadystatechange = UseResultsCallBack;
xmlHttpObj.send(envelope);

xmlHttpObj 是一个有效的 xmlHttpRequest 对象,selectedZip 是一个邮政编码。这都是客户端代码,所以可能存在某种跨域问题,但我不认为这是这种情况下的问题......

【问题讨论】:

  • 此页面是否托管在wsf.cdyne.com 上?如果不是,那么你有一个跨域问题(特别是同源策略)
  • 提示:我从来没有在 ajax 请求中使用绝对 url。始终使用相对 url 并让浏览器设置域名。我还用健全的脚本检查了这一点。结果是它抓住了初级程序员试图发出跨域 ajax 请求。
  • 它不会(也不会)托管在任何地方,只是在我的笔记本电脑上运行。并且通过相对url,你的意思是我应该在请求标头中设置主机,然后在open方法中设置url相对吗?我有类似的东西,但它仍然无法解决任何问题。如果这是一个跨域问题,我将如何解决它?浏览器会将 kabosh 放在调用中吗?
  • 否,在请求头中设置主机将不起作用。该页面必须托管在与 ajax 请求源相同的域上,否则它将无法通过同源策略检查。所以是的,这是一个跨域问题。让我把你的选择放在一个答案中。

标签: javascript ajax soap


【解决方案1】:

根据您的 cmets(其中包括您的问题中未包含的非常重要的信息),您似乎正在尝试执行跨域 ajax 请求。这是不允许的。只允许来自wsf.cdyne.com 的页面向wsf.cdyne.com 发出ajax 请求。甚至来自cdyne.com 的页面也被阻止对wsf.cdyne.com 进行ajax 调用,因为浏览器认为它是一个不同的域。

对此有两种解决方法。第一个是现代解决方案:CORS(跨源资源共享)。这需要wsf.cdyne.com 网站授予您的页面/站点访问其数据的权限。他们可以通过将Access-Control-Allow-Origin 标头添加到他们的HTTP 响应来做到这一点。如果不进行此修改,您将无能为力。有了这个修改,您不需要做任何特别的事情,只需进行常规的 ajax 调用,浏览器就会与他们的站点进行协商。我再次强调,这不是你需要做的事情。这是wsf.cdyne.com 管理员需要做的事情。所以联系他们的管理员。

但是,CORS 协议可能对您没有多大帮助。这是因为大多数浏览器都对让您破坏同源策略设置了严格的限制。例如,尽管 W3C 规范允许使用 * 来源,让每个人都可以向网站发出 ajax 请求,但出于安全原因,一些浏览器不支持它。此外,即使可能支持*,某些浏览器也不允许本地托管文件(即未托管在服务器上的页面)使用 CORS。有些甚至更严格地要求服务器有一个域名,而不仅仅是一个 IP 地址。

有关 CORS 的更多信息,请参阅以下链接:

  1. https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS

  2. cross domain ajax

第二种解决方法是更传统的方法。阻止您发出请求的是网络浏览器。像 javascript、Perl、PHP、C 和 Java 这样的编程语言没有这样的限制。所以解决方案很明显:不要从浏览器发出请求。将其代理到您的服务器。

请记住,以您选择的任何语言编写的代理脚本都必须托管在与您的网页相同的域中。同样,这意味着它不适用于本地文件。但是在本地计算机上运行一个最小的 Web 服务器应该不会太难。

代理甚至不需要在服务器上。 YUI 例如使用 Flash 小程序来代理跨域请求。如果我没记错的话,你也可以用 Java 试试。但 Flash 和 Java 最近都开始关闭安全漏洞,因此这种情况可能不会永远持续下去。更不用说供应商开始放弃这两种技术了。

对我来说,最好的选择是简单地运行一个 Web 服务器并为您想要向其发出 ajax 请求的页面编写一个代理脚本。警告:不要编写通用代理脚本。垃圾邮件发送者和僵尸网络运营商一直在寻找开放的网络代理来掩盖他们的踪迹。

【讨论】:

  • 感谢您的详细回复!出于好奇,如果wsf.cdyne.com 服务器已经安装了CORS,那么我发布的代码应该没有问题吗?不幸的是,由于这是一项作业,教授的“正确”答案是在您的浏览器设置中启用跨域数据访问(这样做可以使上述代码完美运行),并且使用来自您的服务器的调用是额外的功劳.
  • 是的,默认情况下,除了跨域 URL 之外,CORS ajax 调用和常规 ajax 调用没有区别。浏览器将在称为预检的步骤中为您自动协商。如果您不想进行预检,则需要在 ajax 请求中添加一些标头。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多