3

我正在使用 ajax 调用基于 WCF REST 的服务。

在页面加载之前调用 ajax 方法。我希望在 ajax 请求的标头中发送一个“令牌”。在提琴手这就是我所看到的:

1.) 对服务的请求,但标头中没有令牌。(AJAX 调用失败) 2.) 对同一服务的请求,但标头中有令牌。(AJAX 调用通过)

之后,一切都在 chrome 和 safari 上运行良好。但是在 IE 10 和 Mozilla 上只有一个服务调用。结果,服务调用在 IE 10 和 Mozilla 中失败,因为请求的标头中没有令牌。

这是我调用的方法:

function callservice (method, serviceUrl, params, successHandler, errorHandler) {
    $.ajax({
        crossDomain: true,
        type: method,
        url: serviceUrl,
        beforeSend: function (XMLHttpRequest) { XMLHttpRequest.setRequestHeader("Authorization", Token); },
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: successHandler,
        error: errorHandler
    });
    function photos(data) {
        alert(data);
        console.log(data);
    };
}

我控制 Web 服务和应用程序(调用此 Web 服务)。当应用程序和 Web 服务都托管在本地主机上时,不会出现此问题。在这种情况下,只有一个成功的服务调用。但是在有跨域调用的时候有两个AJAX调用。

我的问题是为什么 AJAX 请求没有在第一次尝试时发送令牌?为什么令牌只在第二个 AJAX 调用中发送?

任何形式的帮助将不胜感激。

4

3 回答 3

7

问题出在CORS。以前,浏览器不允许向与客户端不同的域发出ajax请求,因为它被认为是安全威胁。现代浏览器可以发出跨域ajax请求,只要服务器与客户端合作。所以当有来自浏览器的跨域请求时,实际上会发生这种情况:

1.)首先,浏览器向服务发送“预检”请求,以从 WCF 服务收集授权信息(在我的情况下,这是一个标头方法为“OPTIONS”的请求)。作为回报,Web 服务发送访问控制允许来源作为其响应标头的一部分。由于此请求而在提琴手上显示的错误是 HTTP 500 错误。此 AJAX 请求在数据字段中没有任何内容,因为它只是一种查找 WCF 服务授权详细信息的方法。

2.) Chrome 和 Safari 然后向 Web 服务发出第二个请求,因为它们拥有服务的授权详细信息。而 Firefox 和 IE 不喜欢向该服务发出第二个 ajax 请求,因为存在 HTTP 500 错误飞行前的请求。因此,Chrome 和 Safari 都能够与该服务进行通信。

因此,解决方案是修改来自 WCF 服务的响应,以防出现“预检请求”。我修改了服务发送的响应,以防出现“预检请求”以发送 HTTP 200 OK 响应。这允许 IE 和 Mozilla 等浏览器在预检请求之后发送实际请求。

这是我提到的来源之一: http ://www.bennadel.com/blog/2327-Cross-Origin-Resource-Sharing-CORS-AJAX-Requests-Between-jQuery-And-Node-js.htm

希望这可以帮助面临同样问题的人。

于 2012-12-28T15:09:47.827 回答
0

跨域调用属于同源策略。默认情况下您无法拨打电话。您需要使用CORS或 JSONP 或代理。

于 2012-11-28T21:51:25.450 回答
-1

XMLHttpRequest:除非他们更改它,否则使用 MS Explorer,您将需要使用 ActiveXObject("Microsoft.XMLHTTP")。对于我用纯 JS 进行的 ajax 调用,我使用这一行根据浏览器创建对象:

if (window.XMLHttpRequest){
   //for most BRowsers
   r = new XMLHttpRequest(); 
} else{ 
   //for Explorer
   r = new ActiveXObject("Microsoft.XMLHTTP");
}

然后在我的例子中将你的 beforesend 应用到这里创建的对象(r​​)。我真的相信这是你的EI问题。但未测试。

于 2012-11-28T21:42:01.220 回答