基于jQuery AJAX SOAP的Web服务和CORS(跨域资源共享)

时间:2013-04-02 14:55:08

标签: jquery web-services soap cors

我已经有几个星期了,我试图让我的一个基于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"
});
}

1 个答案:

答案 0 :(得分:5)

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

CORS不仅限于GET方法,也不仅限于JSONP风格的调用。

JSONP是Web开发人员在CORS标准化之前使用的一种技术,用于向除了为页面提供服务的主机之外的主机执行AJAX请求。 JSONP的工作原理是在页面中插入<script>标记。它需要服务器参与,通常是通过将JSON结果包装到函数的调用中,通过callback参数在AJAX调用中命名。请参阅此答案: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不需要在回调函数中包含结果或对结果进行任何其他调整,它会处理错误和其他状态代码。有关详情,请参阅此优秀overview of CORS