`
flex_莫冲
  • 浏览: 1095713 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

jQuery 跨域访问问题解决方法

 
阅读更多
浏览器端跨域访问一直是个问题, 多数研发人员对待js的态度都是好了伤疤忘了疼,所以病发的时候,时不时地都要疼上一疼.记得很久以前使用iframe 加script domain 声明,yahoo js util 的方式解决二级域名跨域访问的问题.
时间过得好快,又被拉回js战场时, 跨域问题这个伤疤又开疼了.

好在,有jquery帮忙,跨域问题似乎没那么难缠了.这次也借此机会对跨域问题来给刨根问底,结合实际的开发项目,查阅了相关资料,算是解决了跨域问题..有必要记下来备忘.

跨域的安全限制都是指浏览器端来说的.服务器端是不存在跨域安全限制的,
所以通过本机服务器端通过类似httpclient方式完成“跨域访问”的工作,然后在浏览器端用AJAX获取本机服务器端“跨域访问”对应的url.来间接完成跨域访问也是可以的.但很显然开发量比较大,但限制也最少,很多widget开放平台server端(如sohu博客开放平台)其实就么搞的.不在本次讨论范围.

要讨论的是浏览器端的真正跨域访问,推荐的是目前jQuery $.ajax()支持get方式的跨域,这其实是采用jsonp的方式来完成的.

真实案例:
复制代码 代码如下:

var qsData = {'searchWord':$("#searchWord").attr("value"),'currentUserId':$("#currentUserId").attr("value"),'conditionBean.pageSize':$("#pageSize").attr("value")};
$.ajax({
async:false,
url: http://跨域的dns/document!searchJSONResult.action,
type: "GET",
dataType: 'jsonp',
jsonp: 'jsoncallback',
data: qsData,
timeout: 5000,
beforeSend: function(){
//jsonp 方式此方法不被触发.原因可能是dataType如果指定为jsonp的话,就已经不是ajax事件了
},
success: function (json) {//客户端jquery预先定义好的callback函数,成功获取跨域服务器上的json数据后,会动态执行这个callback函数
if(json.actionErrors.length!=0){
alert(json.actionErrors);
}
genDynamicContent(qsData,type,json);
},
complete: function(XMLHttpRequest, textStatus){
$.unblockUI({ fadeOut: 10 });
},
error: function(xhr){
//jsonp 方式此方法不被触发.原因可能是dataType如果指定为jsonp的话,就已经不是ajax事件了
//请求出错处理
alert("请求出错(请检查相关度网络状况.)");
}
});

注意:$.getJSON(" http://跨域的dns/document!searchJSONResult.action?name1="+value1+"&jsoncallback=?",
function(json){
if(json.属性名==值){
// 执行代码
}
});
这种方式其实是上例$.ajax({..}) api的一种高级封装,有些$.ajax api底层的参数就被封装而不可见了.
这样,jquery就会拼装成如下的url get请求
http:// 跨域的 dns/document!searchJSONResult.action?&jsoncallback=jsonp1236827957501&_=1236828192549&searchWord=%E7%94%A8%E4%BE%8B&currentUserId=5351&conditionBean.pageSize=15

在响应端(http://跨域的dns/document!searchJSONResult.action),
通过 jsoncallback = request.getParameter("jsoncallback") 得到jquery端随后要回调的js function name:jsonp1236827957501
然后 response的内容为一个Script Tags:"jsonp1236827957501("+按请求参数生成的json数组+")";
jquery就会通过回调方法动态加载调用这个js tag:jsonp1236827957501(json数组);
这样就达到了跨域数据交换的目的.

jsonp的最基本的原理是:动态添加一个<script>标签,而script标签的src属性是没有跨域的限制的。这样说来,这种跨域方式其实与ajax XmlHttpRequest协议无关了.
这样其实"jQuery AJAX跨域问题"就成了个伪命题了,jquery $.ajax方法名有误导人之嫌.
如果设为dataType: 'jsonp', 这个$.ajax方法就和ajax XmlHttpRequest没什么关系了,取而代之的则是JSONP协议.
JSONP是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问
JSONP即JSON with Padding。由于同源策略的限制,XmlHttpRequest只允许请求当前源(域名、协议、端口)的资源。如果要进行跨域请求,
我们可以通过使用html的script标记来进行跨域请求,并在响应中返回要执行的script代码,其中可以直接使用JSON传递javascript对象。
这种跨域的通讯方式称为JSONP。

jsonCallback 函数jsonp1236827957501(....): 是浏览器客户端注册的,获取跨域服务器上的json数据后,回调的函数

Jsonp原理:

首先在客户端注册一个callback (如:'jsoncallback'), 然后把callback的名字(如:jsonp1236827957501)传给服务器。

此时,服务器先生成 json 数据。

然后以 javascript 语法的方式,生成一个function , function 名字就是传递上来的参数 'jsoncallback'的值 jsonp1236827957501 .

最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。

客户端浏览器,解析script标签,并执行返回的 javascript 文档,此时javascript文档数据,作为参数,
传入到了客户端预先定义好的 callback 函数(如上例中jquery $.ajax()方法封装的的success: function (json))里.(动态执行回调函数)

可以说jsonp的方式原理上和<script src="http://跨域/...xx.js"></script>是一致的(qq空间就是大量采用这种方式来实现跨域数据交换的) .JSONP是一种脚本注入(Script Injection)行为,所以也有一定的安全隐患.

注意,jquey是不支持post方式跨域的.
为什么呢?
虽然采用post +动态生成iframe是可以达到post跨域的目的(有位js牛人就是这样把jquery1.2.5 打patch的),但这样做是一个比较极端的方式,不建议采用.
也可以说get方式的跨域是合法的,post方式从安全角度上,被认为是不合法的, 万不得已还是不要剑走偏锋..

client端跨域访问的需求看来也引起w3c的注意了,看资料说html5 WebSocket标准支持跨域的数据交换,应该也是一个将来可选的跨域数据交换的解决方案.


script请求返回JSON实际上是脚本注入。它虽然解决了跨域问题,但它不是万能的。

1,不能接受HTTP状态码

2,不能使用POST提交(默认GET)

3,不能发送和接受HTTP头

4,不能设置同步调用(默认异步)

...

其最严重的就是不能提供错误处理,如果请求的代码正常执行那么会得到正确的结果。如果请求失败,如404,500之类,那么可能什么都不会发生。这篇在上一篇的基础上将着重解决JSONP的错误处理。

说可能是因为有些浏览器还是可以提供一些错误处理的。如IE9/10/Firefox/Safari/Chrome都支持script的onerror事件,如果请求失败,在onerror上可以进行必要的回调处理。但IE6/7/8/Opera却不支持onerror。这就是令人头疼的地方,打造一个完美的Sjax不太容易。

只要解决了IE6/7/8/Opera的onerror,整个就ok了。思路是逆向思维:请求成功则成功回调,否则就是失败回调。不拿onerror说事,因为它压根没onerror。因此只能那onload说事。就好比以下推论:

“你是对的” 推断出 “你没错”

因为我没办法知道你是“错的”。但我知道你是“对的”,只能拿是否对去推断你是否错了。

最后的实现细节如下:

1,IE9/Firefox/Safari/Chrome 成功回调使用onload事件,错误回调使用onerror事件

2,Opera 成功回调也使用onload事件(它压根不支持onreadystatechange),由于其不支持onerror,这里使用了延迟处理。即等待与成功回调success,success后标志位done置为true。failure则不会执行,否则执行。这里延迟的时间取值很有技巧,之前取2秒,在公司测试没问题。但回家用3G无线网络后发现即使所引用的js文件存在,但由于网速过慢,failure还是先执行了,后执行了success。所以这里取5秒是比较合理的。虽然这种方式间接实现了failure,但不彻底。

3,IE6/7/8成功回调使用onreadystatechange事件,错误回调几乎是很难实现的。令人恶心的是即使请求的资源文件不存在(404)。它的readyState也会经历“loaded”状态。这样你就没法区分请求成功或失败。最后使用前后台一起协调的机制解决最后的这个难题。无论请求成功或失败都让其调用callback(true)。 此时已经将区别成功与失败的逻辑放到了callback中,如果后台没有返回jsonp则调用failure,否则调用success。

接口:

Sjax.load(url, {
data // 请求参数 (键值对字符串或js对象)
success // 请求成功回调函数
failure // 请求失败回调函数
scope // 回调函数执行上下文
timestamp // 是否加时间戳
});

示例:

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>sjax_0.3.js by snandy</title>
<script src="http://files.cnblogs.com/snandy/sjax_0.3.js"></script>
</head>
<body>
<input type="button" value="Get Name" onclick="clk()"/>
<script type="text/javascript">
function clk(){
Sjax.load('jsonp66.js', {
success : function(){alert(jsonp.name)},
failure : function(){alert('error');}
});
}
</script>
</body>
</html>

以上html,点击“Get Name”按钮,调用clk函数。因为请求的资源jsonp66.js压根不存在。各浏览器下都会弹出“error”,当然Opera中会延迟一些。好了,本系列结束。
分享到:
评论

相关推荐

    JQuery跨域访问解决方案

    jQuery作为流行的JavaScript库,提供了一些机制来处理跨域访问。 JQuery的跨域解决方案主要依赖于JSONP(JSON with Padding)技术。JSONP是一种绕过同源策略的方式,它利用HTML中的`&lt;script&gt;`标签没有同源策略限制...

    jquery 跨域访问问题解决方法(笔记)

    这篇文章主要讲述了解决jQuery跨域访问问题的方法,并且通过一个具体的案例来说明了问题的解决过程。 首先,让我们明确什么是跨域访问问题。跨域访问指的是当一个网页试图从不同域名的服务器请求资源时,由于浏览器...

    jQuery跨域问题解决方案

    总结起来,解决jQuery跨域问题主要包含两方面内容:第一是理解跨域问题及其背后的同源策略;第二是掌握通过JSONP实现跨域请求的具体步骤和注意事项。通过上述方法,前端开发人员可以较为轻松地从不同域的服务器上...

    jquery下利用jsonp跨域访问实现方法

    JSONP是一种解决跨域问题的技术,其核心思想是利用`&lt;script&gt;`标签不受同源策略限制的特性。当浏览器解析到`&lt;script&gt;`标签时,会发出一个GET请求,而无论该URL是否与当前页面的源相同。服务器返回的不是普通的JSON...

    javascript/jquery 跨域访问

    JavaScript 和 jQuery 是Web开发中广泛使用的两种技术,它们在实现跨域访问方面起着关键作用。跨域访问是Web应用程序中常见的需求,特别是在Ajax请求、API调用或数据共享时。由于浏览器的安全策略,不同域名、协议或...

    jQuery跨域问题

    jQuery跨域问题主要涉及到以下几种情况: 1. JSONP(JSON with Padding):JSONP是一种绕过同源策略的方法,通过动态插入`&lt;script&gt;`标签来请求数据。jQuery的`$.ajax()`或`$.getScript()`函数支持JSONP。当设置`...

    jquery下利用jsonp跨域访问实现方法.docx

    JSONP(JSON with Padding)...总之,JSONP是jQuery中实现跨域访问的一种常见方法,尤其在不支持CORS的旧浏览器环境中非常有用。但随着技术的发展,CORS已成为更推荐的跨域解决方案,因为它提供了更多的控制和安全性。

    跨域访问解决方法-jsonp

    跨域访问是Web开发中一个常见的挑战,尤其是在进行Ajax异步请求时,浏览器的同源策略(Same-origin policy)会限制JavaScript从一个源获取另一个源的数据。为了解决这个问题,开发者通常采用JSONP(JSON with ...

    js解决跨域访问问题

    ### JS解决跨域访问问题详解 #### 一、引言 在现代Web开发中,跨域访问问题是开发者经常面临的一个挑战。特别是在使用JavaScript进行前后端交互时,由于浏览器的同源策略限制,开发者经常会遇到跨域问题。本文将...

    jquery跨域获取json

    总结来说,"jquery跨域获取json"是一个关于JavaScript编程和jQuery库如何通过JSONP技术解决跨域获取数据的问题。在实际开发中,了解并掌握这一技术对前端开发者尤其重要,因为很多API和数据服务都是部署在不同的域名...

    jquery解决客户端跨域访问问题

    客户端“跨域访问”一直是一个头疼的问题,好在有jQuery帮忙,从jQuery-1.2以后跨域问题便迎刃而解。由于自己在项目中遇到跨域问题,借此机会对跨域问题来刨根问底,查阅了相关资料和自己的实践,算是解决了跨域问题...

    jQuery 跨域访问解决原理案例详解

    jQuery跨域访问是指在浏览器端使用jQuery进行AJAX请求时,处理不同源策略所引起的跨域问题。不同源策略是浏览器为了安全考虑而实施的一种限制,它阻止了来自不同域名、端口或协议的页面相互请求资源。这种策略防止了...

    jquery ajax跨域html前台 php后台

    在解决跨域问题时,我们可以利用jQuery的`jsonp`模式。JSONP(JSON with Padding)是一种绕过同源策略的方法,它利用`&lt;script&gt;`标签可以跨域加载脚本的特性。 在描述中提到的"jquery ajax json 跨域不解释,代码很...

    jquery跨域调用webservice

    ### jQuery 跨域调用 WebService 的实现方法 在现代Web开发中,跨域问题是一个常见的挑战,尤其是在涉及不同源的服务交互时。本文将详细解释如何利用jQuery通过JSONP(JSON with Padding)的方式实现跨域调用...

    JQuery Ajax 跨域访问的解决方案

    要解决这个问题,有几种方法可以实现跨域访问: 1. 本域和子域的相互访问:当两个资源位于同一主域名但不同的子域名下时,例如***和***,可以通过设置document.domain属性将不同子域的源统一为相同的主域名,从而...

    Ajax +jquery跨域获取JSON

    这里的"Ajax + jQuery跨域获取JSON"是一个典型的Web开发技术应用场景,主要用于解决Web应用程序中不同源之间的数据共享问题。在本案例中,开发者成功地实现了跨域请求以获取JSON数据,并将这些数据用于展示天气预报...

Global site tag (gtag.js) - Google Analytics