17

几个星期以来,我一直在尝试让我的一个基于 jQuery AJAX SOAP 的跨域 Web 服务从我为我的一位客户编写的 jQuery 插件中工作。我所做的大部分研究似乎表明这是不可能的,因为 CORS 或跨域资源共享只允许 jasonP (GET) 类型的调用。

我终于想出了如何让它发挥作用,并认为我会分享我必须做的事情。

首先要了解的是,在支持 CORS 的浏览器中,服务器位于另一个域中,除 GET 之外的任何其他参数(以及其他参数)都将导致所谓的预检检查。这意味着浏览器将向服务器询问允许执行的选项列表。除非服务器返回确切的选项列表以允许基于 SOAP 的 Web 服务,否则即使在发出实际请求之前,调用也会失败。

您需要做的是让 Web 服务器(在我的示例中为 IIS7.5)返回正确的选项列表。
为此,您可以在 inetpub\wwwroot 文件夹中配置 web.config 文件(如果没有,只需创建它并将以下内容复制到其中)。

我的 web.config 文件看起来像这样。

重要的是,一旦我意识到这一切都按预期工作,一切都是区分大小写的。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
 <system.webServer>
  <httpProtocol>
   <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
    <add name="Access-Control-Allow-Methods" value="POST, GET, OPTIONS, PUT, DELETE" />
    <add name="Access-Control-Allow-Headers" value="content-type,soapaction,x-requested-with" />      
    </customHeaders>
   </httpProtocol>
        <handlers accessPolicy="Read, Execute, Script" />
 </system.webServer>
</configuration>

我的 jQuery AJAX 代码如下所示。

var getNextJobId = function()
{
  var se = '';
  se = se + '<?xml version="1.0" encoding="UTF-8" standalone="no"?>';
  se = se + '<soap-env:Envelope xmlns:soap-env="http://www.w3.org/2003/05/soap-envelope">';
  se = se + '<soap-env:Body>';
  se = se + '<ebas:getNextJobIdRequest xmlns:ebas="http://www.ebasetech.com">';
  se = se + '<ebas:ORGCODE>' + plugin.settings.orgcode + '</ebas:ORGCODE>';
  se = se + '</ebas:getNextJobIdRequest>';
  se = se + '</soap-env:Body>';
  se = se + '</soap-env:Envelope>';
  $.ajax(
  {
    url: params.webserviceTargetUrl,
beforeSend: function(xhr)
{
  xhr.setRequestHeader("SOAPAction", "getNextJobId");
},
type: "POST",
dataType: "xml",
data: se,
crossDomain: true,
headers: {"X-Requested-With": "XMLHttpRequest"},
async: false,
success: function(xml)
{
  params.jobId =   $(xml).find("ebas\:JOBID").text();
},
failure: function(xml)
{
  params.webserviceFailure = $(xml).text();
},
      contentType: "charset=UTF-8"
});
}
4

1 回答 1

5

“这是不可能的,因为 CORS 或跨域资源共享只允许 jasonP (GET) 类型的调用。”

CORS 不限于 GET 方法,也不限于 JSONP 样式的调用。

JSONP 是一种在 CORS 标准化之前 Web 开发人员使用的技术,用于向服务于页面的主机以外的主机执行 AJAX 请求。JSONP 通过<script>在页面中插入标签来工作。它需要服务器参与,通常通过将 JSON 结果包装在对函数的调用中,在 AJAX 调用中通过callback参数命名。看到这个答案: what-is-jsonp-all-about

正如您所指出的,JSONP 仅限于执行 GET 方法,因为<script>只执行 GET。它也有其他问题,例如无法处理错误。例如,如果返回 400 响应,则脚本根本不会被浏览器执行,而不是为 AJAX 调用执行 JS 错误处理程序。

CORS 是一个较新的标准。它还需要服务器参与,因为它必须处理预检检查,并使用额外的 HTTP 标头,例如:Access-Control-Allow-OriginAccess-Control-Allow-MethodsAccess-Control-Allow-Headers,您在问题的编辑中很好地描述了这些标头。它不限于 GET 方法。相反,它仅限于由Access-Control-Allow-Methods标头中的预检检查结果指定的那些方法。CORS 不需要在回调函数中包装结果或对结果进行任何其他调整,它可以处理错误和其他状态代码。有关更多信息,请参阅 CORS 的出色概述。

于 2013-06-13T16:52:01.737 回答