1.什么是跨域?
跨域,JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象。简单地理解就是因为JavaScript同源策略的限制,a.com 域名下的js无法操作b.com或是c.a.com域名下的对象。
同源策略,它是由Netscape提出的一个著名的安全策略。现在所有支持JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面当一个百度浏览器执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。
更详细的说明可以看下表:

URL 说明 是否允许通信
http://www.a.com/a.js
http://www.a.com/b.js
同一域名下 允许
http://www.a.com/lab/a.js
http://www.a.com/script/b.js
同一域名下不同文件夹 允许
http://www.a.com:8000/a.js
http://www.a.com/b.js
同一域名,不同端口 不允许
http://www.a.com/a.js
https://www.a.com/b.js
同一域名,不同协议 不允许
http://www.a.com/a.js
http://70.32.92.74/b.js
域名和域名对应ip 不允许
http://www.a.com/a.js
http://script.a.com/b.js
主域相同,子域不同 不允许
http://www.a.com/a.js
http://a.com/b.js
同一域名,不同二级域名(同上) 不允许(cookie这种情况下也不允许访问
http://www.cnblogs.com/a.js
http://www.a.com/b.js
不同域名 不允许

特别注意两点:
(1).如果是协议和端口造成的跨域问题“前台”是无能为力的,
(2).在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。
“URL的首部”指window.location.protocol +window.location.host,也可以理解为“Domains, protocols and ports must match”。

2.跨域请求数据解决方案
(1).document.domain+iframe的设置
对于主域相同而子域不同的例子,可以通过设置document.domain的办法来解决。
(2).动态创建Script
虽然浏览器默认禁止了跨域访问,但并不禁止在页面中引用其他域的JS文件,并可以自由执行引入的JS文件中的function(包括操作cookie、Dom等等)。
(3).利用iframe和location.hash
这个办法比较绕,但是可以解决完全跨域情况下的脚步置换问题。原理是利用location.hash来进行传值。
(4).Window.name实现的跨域数据传输
iframe的src属性由外域转向本地域,跨域数据即由iframe的window.name从外域传递到本地域。这个就巧妙地绕过了浏览器的跨域访问限制,但同时它又是安全操作。
(5).使用HTML5 postMessage
HTML5中最酷的新功能之一就是 跨文档消息传输Cross Document Messaging。
(6).利用flash
上述,六种方式都可以处理JavaScript的跨域请求数据问题,详细参见:Rain Man的《JavaScript跨域总结与解决办法》。
除了上面六种方式,大家平时估计都在用脚本框架开发,在JQuery框架和ExtJs框架中处理JS跨域问题,常用JSONP来处理。

3.什么是JSONP?
JSONP(JSON with Padding)是一个非官方的协议,它允许在服务器端集成Script Tags返回至客户端,通过Javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。
由于同源策略的限制,XMLHttpRequest只允许请求当前源(域名、协议、端口)的资源,为了实现跨域请求,可以通过script标签实现跨域请求,然后在服务端输出JSON数据并执行回调函数,从而解决了跨域的数据请求。

4..JSONP如何产生的?
(1).跨域访问无权限。
众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,不管是静态页面、动态网页、web服务、WCF,只要是跨域请求,都无权限;
(2)."src"属性标签有跨域能力。
发现在Web页面上调用js文件时则不受是否跨域的影响(不仅如此,拥有"src"属性的标签都拥有跨域能力,比如<script>、<img>、<iframe>);
(3).将数据装进JS格式数据。
如果想通过纯Web端(ActiveX控件、服务端代理、HTML5之Websocket等方式不算)跨域访问数据就只有一种可能,就是在远程服务器上设法把数据装进js格式的数据里,供客户端调用和进一步处理;
(4).JSON格式承载数据适合。
有一种JSON的纯字符数据格式可以简洁的描述复杂数据,更妙的是JSON还被JS原生支持,所以在客户端几乎可以随心所欲的处理这种格式的数据;
(5).动态生成JSON格式数据。
Web客户端可以通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件,显而易见,服务器之所以要动态生成JSON文件,目的在于把客户端需要的数据装入进去。
(6).JSON数据成功回调到客户端。
客户端在对JSON文件调用成功之后,也就获得了自己所需的数据,剩下的就是按照自己需求进行处理和展现了,这种获取远程数据的方式看起来非常像AJAX,但实质上是不一样。
(7).形成一种非正式传输协议JSONP。
为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回的数据。

5.JSONP的工作原理
JSONP的原理:创建一个回调函数,动态创建Script标签,然后在远程服务上调用这个函数并且将JSON 数据形式作为参数传递,完成回调。将JSON数据填充进回调函数,进行相关的逻辑处理,或许这就是JSONP的JSON+Padding的含义。
(1).跨域简单原理
新建一个asp.net的web程序,添加sample.html网页和一个test.js文件,代码如下:
sample.html的代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<htmlxmlns="http://www.w3.org/1999/xhtml" ><head><title>test</title><scripttype="text/javascript"src="test.js"></script></head><body></body>
</html>

test.js的代码:

 alert("success");

打开sample.html后会跳出"success”这样的这样的信息框,这似乎并不能说明什么, 跨域问题到底怎么解决呢?
现在模拟非同源的环境,把上面的Web程序叫做A程序,再新建一个Web程序叫做B程序,将A程序的test.js文件移除然后拷贝到B程序中。将两个程序都运行起来,Visual Studio会启动内置服务器,假设A程序是localhost:20001,B程序是localhost:20002,这就模拟了一个非同源的环境了(虽然域名相同但端口号不同,所以是非同源的)。

现在改下A程序sample.html里的代码,因为test.js文件在B程序上了,url也就变成了localhost:20002。

sample.html部分代码:

<scripttype="text/javascript"src="http://localhost:20002/test.js"></script>

请保持AB两个Web程序的运行状态,当你再次刷新A程序localhost:20001/sample.html的时候,和原来一样跳出了"success"的对话框,这样就成功访问到了非同源的B程序localhost:20002/test.js这个所谓的远程服务了。到这里,大家应该已经大概明白如何跨域访问的原理了。
<script>标签的src属性并不被同源策略所约束,所以可以获取任何服务器上脚本并执行。

(2).跨域实现CallBack
继续修改代码,实现JSONP的JavaScript callback形式。
修改程序A中sample的代码:

<scripttype="text/javascript">//回调函数functioncallback(data) {alert(data.message);}</script>
<scripttype="text/javascript"src="http://localhost:20002/test.js"></script>

程序B中test.js的代码:

//调用callback函数,并以json数据形式作为阐述传递,完成回调
callback({message:"success"});

这其实就是JSONP的简单实现模式,或者说是JSONP的原型:创建一个回调函数,然后在远程服务上调用这个函数并且将JSON 数据形式作为参数传递,完成回调。
(3).跨域实现动态JS脚本

怎么让远程js知道它应该调用的本地函数叫什么名字?毕竟是jsonp的服务者都要面对很多服务对象,而这些服务对象各自的本地函数都不相同。只要服务端提供的js脚本是动态生成的就可以,这样调用者可以传一个参数过去告诉服务端“我想要一段调用XXX函数的js代码,请你返回给我”,于是服务器就可以按照客户端的需求来动态生成js脚本并响应了。
程序A中sample的代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<htmlxmlns="http://www.w3.org/1999/xhtml">
<head><title></title><scripttype="text/javascript">//得到航班信息查询结果后的回调函数varflightHandler= function(data){alert('你查询的航班结果是:票价' +data.price+ '元,余票' +data.tickets+ '张。');};//提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)varurl= "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler";//创建script标签,设置其属性varscript=document.createElement('script');
   script.setAttribute("type","text/javascript");
   script.setAttribute('src', url);
//把script标签加入head,此时调用开始
document.getElementsByTagName('head')[0].appendChild(script);</script>
</head>
<body>
</body>
</html>

这样不直接把远程js文件写死,而是编码实现动态查询,而这也正是jsonp客户端实现的核心部分,其重点也就在于如何完成jsonp调用的全过程。
看到调用的url中传递了一个code参数,告诉服务器我要查的是CA1998次航班的信息,而callback参数则告诉服务器,本地回调函数叫做flightHandler,所以请把查询结果传入这个函数中供本地调用。
程序B中test.js的代码:

flightHandler({
"code": "CA1998",
"price": 1780,
"tickets": 5
});

我们看到,传递给flightHandler函数的是一个json,它描述了航班的基本信息。运行一下页面,成功弹出提示窗口,jsonp的执行全过程顺利完成!

6.JQuery和ExtJs实现JSONP
(1).JQuery的JSONP跨域实现
<1>.$.getJSON
jQuery框架支持JSONP,可以使用$.getJSON(url,[data],[callback])方法(详细可以参考http://api.jquery.com/jQuery.getJSON/)。继续修改程序A的代码,改用jQuery的getJSON方法来实现(下面的例子没用用到向服务传参,所以只写了getJSON(url,[callback])):

<scripttype="text/javascript"src="http://code.jquery.com/jquery-latest.js"></script>
<scripttype="text/javascript">$.getJSON("http://localhost:20002/MyService.ashx?callback=?",function(data){
alert(data.name+ "is a a" +data.sex);
});</script>

要注意的是在url的后面必须添加一个callback参数,这样getJSON方法才会知道是用JSONP方式去访问服务,callback后面的那个问号是内部自动生成的一个回调函数名。这个函数名可以debug看一下,比如jQuery17207481773362960666_1332575486681。

<2>.$.ajax
假如说我们想指定自己的回调函数名,或者说服务上规定了固定回调函数名该怎么办呢?可以使用$.ajax方法来实现(参数较多,详细可以参见http://api.jquery.com/jQuery.ajax)。

<scripttype="text/javascript"src="http://code.jquery.com/jquery-latest.js"></script>
<scripttype="text/javascript">$.ajax({url:"http://localhost:20002/MyService.ashx?callback=?", dataType:"jsonp",jsonpCallback:"person",success:function(data){alert(data.name+ "is a a" +data.sex);}
});</script>

jsonpCallback就是指定我们自己的回调方法名person,远程服务接受callback参数的值就不再是自动生成的回调名,而是person。dataType是指定按照JSOPN方式访问远程服务。

(2).ExtJs的JSONP跨域实现
<1>.Ext.data.JsonP.request
ExtJS4.1的Ext.data.JsonP.request实现跨域访问:

//跨域请求,MsgUrl为其他站点地址
Ext.data.JsonP.request({url: MsgUrl + '/Home/InitializeComet',timeout: 300000,params: { loginId: LoginId },callbackKey: "jsonPCallback",success: function(result) {if (result.rettype == 'true') {me.Comet.privateToken = result.msg;me.RegisterComet();} else {alert(result.msg);}},failure: function(result) {alert(result);}
});

其中跨域请求的要点是类名:Ext.data.JsonP和callbackKey的参数。
“jsonPCallback”该名称将作为Jsonp请求的方法名传递到服务器端,获取该请求的URL:
http://10.0.13.64:89/Home/InitializeComet?loginId=0001&jsonPCallback=Ext.data.JsonP.callback1&_dc=1370687739484

<2>.Ext.data.ScriptTagProxy

var ss = new Ext.data.ScriptTagProxy({//url: 'http://10.128.3.104/edi/rest/GetBillCaseInfo',url: 'testjson.do',callbackParam: "_callback",headers: { 'Authorization': 'Basic YWRtaW46YWRtaW4xMjM=' }
});
ss.load({ '_out': 'json' },new Ext.data.JsonReader({ root: "ROWSET.ROW" },[{ name: 'CaseCode', mapping: 'CaseCode' },{ name: 'CaseName', mapping: 'CaseName'}]),function (recordsBlock, arg, isok) {alert(Ext.encode(recordsBlock));alert(Ext.encode(recordsBlock.records[0].data));
}
);
Ext.Ajax.request({url: 'http://10.128.3.104/edi/rest/GetBillCaseInfo',//url: 'testjson.do',scriptTag: true,success: function (req) {alert(req.responseText);},failure: function (req) {alert(req.responseText);},headers: { 'Authorization': 'Basic YWRtaW46YWRtaW4xMjM=' },params: { _out: 'json' }
});

7.AJAX与JSONP的异同
(1).Ajax和Jsonp是两种技术。
Ajax和Jsonp这两种技术在调用方式上“看起来”很像,目的也一样,都是请求一个URL,然后把服务器返回的数据进行处理,因此JQuery和EXT等框架都把Jsonp作为Ajax的一种形式进行了封装;
(2).Ajax和Jsonp实现原理不同。
Ajax和Jsonp在本质实现上有差别。Ajax的核心是通过XmlHttpRequest获取非本页内容,而Jsonp的核心则是动态添加<script>标签来调用服务器提供的js脚本。所以说,其实Ajax与jsonp的区别不在于是否跨域,ajax通过服务端代理一样可以实现跨域,Jsonp本身也不排斥同域的数据的获取;
(3).Ajax和Jsonp都是非强制性协议。
Jsonp是一种方式或者说非强制性协议,如同Ajax一样,它也不一定非要用Json格式来传递数据,如果你愿意,字符串都行,只不过这样不利于用Jsonp提供公开服务。
总而言之,Jsonp不是Ajax的一个特例,哪怕Jquery、Ext等巨头把Jsonp封装进了Ajax,也不能改变这一点!

参考博客:
《Ajax与JSON的一些总结》
《JavaScript跨域总结与解决办法》
《深入浅出JSONP--解决ajax跨域问题》
《说说JSON和JSONP,也许你会豁然开朗,含jQuery用例》
《Jquery跨域请求》
《ExtJs学习笔记(23)-ScriptTagProxy+XTemplate+WCF跨域取数据》
《ExtJs与WCF之间的跨域访问》
《jQuery与Extjs的Ajax的跨域访问》

转载于:https://www.cnblogs.com/SanMaoSpace/p/3144851.html

JS、JQuery和ExtJs的跨域处理相关推荐

  1. JQuery - Ajax和Tomcat跨域请求问题解决方法!

    JQuery - Ajax和Tomcat跨域请求问题解决方法! 参考文章: (1)JQuery - Ajax和Tomcat跨域请求问题解决方法! (2)https://www.cnblogs.com/ ...

  2. node.js后端及Vue前端跨域解决方案

    node.js后端及Vue前端跨域解决方案 从目前我了解的情况来看,前后端跨域使用的方式有很多种,这里记录我使用最顺手的一种,即在后端使用cors跨域 node.js后端跨域解决方案 先看后端的入口文 ...

  3. js中的几种跨域方法

    js跨域指的是通过js在不同域之间进行数据传输或通讯,例如ajax通信技术,或者通过js获取页面中iframe的数据.只要有任意一个不同,则协议.域名.端口中有任意一个不同,则彼此成为不同的域. 请注 ...

  4. 使用jsonp及jquery的$.ajax解决跨域问题

    跨域是指代码获得或者更改从另一个域名下获得的文件或者信息.当执行这类操作时,一般会报"拒绝操作","无权限"等 一般我利用三种方法: 服务器后端处理,我直接发送 ...

  5. 利用JQuery jsonp实现Ajax跨域请求 .Net 的*.handler 和 WebService,返回json数据

    原文:  http://blog.csdn.net/polarissky/article/details/6429554 1.新建数据源项目CrossDomain 主要文件如下: 1.Handler. ...

  6. jQuery之ajax的跨域获取数据

    如果获取的数据文件存放在远程服务器上(域名不同,也就是跨域获取数据),则需要使用jsonp类型.使用这种类型的话,会创建一个查询字符串参数 callback=? ,这个参数会加在请求的URL后面.服务 ...

  7. 六、jQuery 中的 AJAX 跨域问题

    第 2 章:jQuery 中的 AJAX 官方中文文档:https://jquery.cuishifeng.cn/jQuery.Ajax.html 2.1 get 请求 $.get(url, [dat ...

  8. jquery读取json文件跨域_跨域方法的若干种方式

    一.跨域的解释 那什么是跨域呢,简单地理解就是因为JavaScript同源策略的限制, a.com 域名下的js无法操作 b.com 或是 c.a.com 域名下的对象.当协议.子域名.主域名.端口号 ...

  9. html中jsonp错误,解决jquery中jsonp格式跨域请求报parsererror的错误

    在vs中创建一个空的mvc项目,在Controllers文件夹中添加一个控制器CommonController,并在该控制器下添加一个action用于获取服务器时间,代码如下: public Acti ...

最新文章

  1. new/delete与malloc/free的区别与联系详解
  2. 一个不错的报表工具 open flash chart 2
  3. Android activity启动模式
  4. Airflow 中文文档:插件
  5. 一个完整的pytorch预训练实现图像分类,模型融合
  6. 【LOJ#10170】国王
  7. rails--bcrypt对密码加密
  8. 二叉树非递归遍历算法(II)中序
  9. c语言打印%-6llu,C语言-输出指定个数的质数
  10. 优化 Laravel 网站打开速度9条
  11. 弘辽科技:拼多多商品搜索热度如何提升?技巧分享
  12. 如何隐藏电脑里的文件或者文件夹?
  13. vmware虚拟机扩展磁盘空间
  14. 1582年日历怎么了_1582年从10月5日到15日到底发生了什么?为何所有日历全是空白?...
  15. mysql 联合主键的作用
  16. java中的加减乘除函数_16版.加减乘除功能函数java
  17. 在微信小程序中实现时间日期的选择,并且显示当前选择的时间日期
  18. 淘宝滑块 tb滑块 x82y x5sec
  19. 关于onKeyDown方法
  20. 虚拟机开启及简单的系统命令

热门文章

  1. hdf5与hdfs的区别
  2. spring 扫描所有_SpringBoot和Spring到底有没有本质的不同?
  3. python性能解决_Python性能优化的20条建议
  4. (c语言)和与积的运算第一篇
  5. Mac中word插入图片保持原来的清晰度
  6. 转-项目管理心得:一个项目经理的个人体会、经验总结
  7. 鸿蒙开发-基础组件介绍及chart组件使用
  8. Geotools简介以及quickstsrt加载shp文件并显示
  9. Java中使用mysqldump实现mysql数据库备份并将sql文件打成zip压缩包
  10. Eclipse中实现SpringBoot与Mybatis整合(图文教程带源码)