我已经有几个星期了,我试图让我的一个基于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"
});
}
答案 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-Origin
,Access-Control-Allow-Methods
和Access-Control-Allow-Headers
,您在编辑中将其描述得很好你的问题。它不仅限于GET方法。相反,它仅限于Access-Control-Allow-Methods
标题中的预检检查结果指定的那些方法。 CORS不需要在回调函数中包含结果或对结果进行任何其他调整,它会处理错误和其他状态代码。有关详情,请参阅此优秀overview of CORS。