Javascript 跨域知识详细介绍


Posted in Javascript onOctober 30, 2016

JS跨域知识总结:

在“跨域”一词经常性地出现以前,我们其实已经频繁地使用它了。如在A网站的img,src指向B网站的某一图片地址,毫无疑问,这在通常情况下都是能正常显示的(且不论防盗链技术);同样,可以使script标签的src属性指向其它网站的脚本资源(在某些情况下甚至鼓励这样做,以便充分利用其它网站的负载优势,减小自身服务器的并发量)。然而,如若使用js去主动请求其它网站的数据,比如ajax方式,就会遇到让人郁闷的跨域问题,这也是我们平常所说的跨域。由于安全原因,跨域访问是被各大浏览器所默认禁止的。这里涉及到同源策略的概念:同源策略阻止从一个域上加载的脚本获取或操作另一个域上的文档属性。也就是说,受到请求的 URL 的域必须与当前 Web 页面的域相同。这意味着浏览器隔离来自不同源的内容,以防止它们之间的操作。

跨域带来的具体安全问题博主没有深究,大伙可以自行脑补。

然而,很多情况下,特别是在互联网持续发展的今天,我们需要请求来自不同合作伙伴或数据提供商的前端接口,在跨域访问的方式没有规范化前(client端跨域访问的需求看来也引起w3c的注意了,看资料说html5 WebSocket标准支持跨域的数据交换,应该也是一个将来可选的跨域数据交换的解决方案),有什么方法能绕过它的限制呢?答案有很多(虽然都很麻烦),最常用的当属所谓的JSONP跨域了。

JSONP原理

JSONP的最基本的原理是:动态添加一个<script>标签,而script标签的src属性是没有跨域的限制的。这样说来,这种跨域方式其实与ajax XmlHttpRequest协议无关了。

JSONP即JSON with Padding。由于同源策略的限制,XmlHttpRequest只允许请求当前源(域名、协议、端口)的资源。如果要进行跨域请求, 我们可以通过使用html的script标记来进行跨域请求,并在响应中返回要执行的script代码。 这种跨域的通讯方式称为JSONP。

来个简单的例子:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" > 
<head> 
  <title>Test Jsonp</title> 
  <script type="text/javascript"> 
      function jsonpCallback(result) 
      { 
      alert(result.msg); 
      } 
    </script> 
  <script type="text/javascript" src="http://crossdomain.com/jsonServerResponse?jsonp=jsonpCallback"></script> 
</head> 
<body> 
</body> 
</html>

简述原理与过程:首先在客户端注册一个callback, 然后把callback的名字传给服务器(这里客户端和服务器约定以key为jsonp的查询字符串值传递)。此时,服务器先生成 json 数据。 然后以 javascript 语法的方式,生成一个function , function 名字就是传递上来的参数 jsonp。最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。客户端浏览器,解析script标签,并执行返回的 javascript 文档,即执行了预定义的callback函数。

从上述简述可以推出:除了返回函数形式的js代码片段,服务端自然能返回所有符合规范的可执行js片段。

JSONP的缺点是:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。(下面还有)

jQuery的Jsonp

如前所述,jsonp并非ajax请求,但是jQuery仍提供与jQuery.ajax一致的方式进行跨域请求:

$.ajax({
  url: 'http://crossdomain.com/jsonServerResponse',
  type: 'GET',
  dataType: 'jsonp',
  jsonp: "callback",
  jsonpCallback: 'functionName',
  success: function (data, textStatus, jqXHR) { }
  //……
});

如上所示,dataType设为jsonp表示这是一次跨域请求,jsonp设为服务端预定的传递函数名称的查询字符串key,而jsonpCallback即为js函数名称;假如jsonpCallback不设置,那么jQuery将自动生成的随机函数名(在window对象中加载一个全局的函数,当代码插入时函数执行,执行完毕后就会被移除),可推断该自动生成的函数会回调上述代码中的success函数。(当手动为jsonpCallback赋值时,不知道success函数会否回调,还是说jQuery会寻找预定义的函数,若找不到则报错?博主懒,以后再试吧。)当然jQuery为我们提供了一个简易版本,$.getJSON,这里就不赘述了。

需要注意的是success函数中的jqXHR参数,在ajax请求中,它是正宗的jqXHR对象,亦可看作是XMLHTTPRequest对象(继承or封装),但是在jsonp请求中却并非如此,几乎不能带给我们如XMLHTTPRequest中最有用的那些信息:它缺少XMLHTTPRequest的请求状态信息,所以并不能触发绝大部分的回调函数,比如error、complete等(jQuery1.9.0),而可以被回调的success函数推测应该是由script标记的load事件触发,这也同ajax依靠XMLHTTPRequest的状态的机制完全不同。经试验,脱胎于jQuery的zepto(v1.1.3),在jsonp请求出现错误,比如加载js文档时头部返回401错误时,error函数会执行,但是该函数的jqXHR参数也同样不是正宗的jqXHR类型,甚至不能通过它获取响应的头部信息,在这种情况下,我们只是被告知某个环节出错了,却并不知道具体的错误信息。类似响应头承载有用信息的场景,博主不建议使用jsonp,可以说,使用jsonp的一个前提是:除了网络异常等非业务异常外,所有业务异常(概括地说,乃是从服务器接收请求到返回响应这段时间内抛出的所有异常)都需要以请求结果的形式直接返回给客户端,便于客户端回调分析。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

Javascript 相关文章推荐
js 匿名调用实现代码
Jun 19 Javascript
jQuery学习3:操作元素属性和特性
Feb 07 Javascript
在HTML代码中使用JavaScript代码的例子
Oct 16 Javascript
js onmousewheel事件多次触发问题解决方法
Oct 17 Javascript
浅析AngularJS中的指令
Mar 20 Javascript
AngularJS基础 ng-keypress 指令简单示例
Aug 02 Javascript
jQuery制作圣诞主题页面 更像是爱情影集
Aug 10 Javascript
JS实现下拉菜单列表与登录注册弹窗效果
Aug 10 Javascript
js实现随机点名系统(实例讲解)
Oct 18 Javascript
详解Chart.js轻量级图表库的使用经验
May 22 Javascript
JavaScript实现简单的隐藏式侧边栏功能示例
Aug 31 Javascript
Vue实现手机号、验证码登录(60s禁用倒计时)
Dec 19 Vue.js
jquery.validate[.unobtrusive]和Bootstrap实现tooltip错误提示问题分析
Oct 30 #Javascript
JS触摸屏网页版仿app弹窗型滚动列表选择器/日期选择器
Oct 30 #Javascript
js模式化窗口问题![window.dialogArguments]
Oct 30 #Javascript
Chrome不支持showModalDialog模态对话框和无法返回returnValue问题的解决方法
Oct 30 #Javascript
原生JS版和jquery版实现checkbox的全选/全不选/点选/行内点选(Mr.Think)
Oct 29 #Javascript
JavaScript计算值然后把值嵌入到html中的实现方法
Oct 29 #Javascript
JS给Array添加是否包含字符串的简单方法
Oct 29 #Javascript
You might like
PHP获取数组的键与值方法小结
2015/06/13 PHP
php根据日期显示所在星座的方法
2015/07/13 PHP
PHP代码维护,重构变困难的4种原因分析
2016/01/25 PHP
PHP大神的十大优良习惯
2016/09/14 PHP
Yii 访问 Gii(脚手架)时出现 403 错误
2018/06/06 PHP
Yii框架应用组件用法实例分析
2020/05/15 PHP
JSON扫盲帖 JSON.as类教程
2009/02/16 Javascript
数组Array进行原型prototype扩展后带来的for in遍历问题
2010/02/07 Javascript
基于jQuery的实现简单的分页控件
2010/10/10 Javascript
页面调用单个swf文件,嵌套出多个方法。
2011/11/21 Javascript
js实现动态改变字体大小代码
2014/01/02 Javascript
jquery实现带二级菜单的导航示例
2014/04/28 Javascript
深入理解JavaScript系列(41):设计模式之模板方法详解
2015/03/04 Javascript
jquery原理以及学习技巧介绍
2015/11/11 Javascript
ie下js不执行的几种可能
2017/02/28 Javascript
js模拟支付宝密码输入框
2017/04/11 Javascript
vue-prop父组件向子组件进行传值的方法
2018/03/01 Javascript
JS中获取 DOM 元素的绝对位置实例详解
2018/04/23 Javascript
nodejs用gulp管理前端文件方法
2018/06/24 NodeJs
微信小程序去除左上角返回键的实现方法
2020/03/06 Javascript
JS函数参数的传递与同名参数实例分析
2020/03/16 Javascript
vue+animation实现翻页动画
2020/06/29 Javascript
在Linux上安装Python的Flask框架和创建第一个app实例的教程
2015/03/30 Python
分析并输出Python代码依赖的库的实现代码
2015/08/09 Python
新手学python应该下哪个版本
2020/06/11 Python
iRobot官网:改变生活的家用机器人品牌
2016/09/20 全球购物
万代美国官网:PREMIUM BANDAI USA
2020/09/11 全球购物
校运会广播稿100字
2014/01/27 职场文书
《山谷中的谜底》教学反思
2014/04/26 职场文书
毕业生工作求职信
2014/06/30 职场文书
幼儿园安全责任书范本
2014/07/24 职场文书
企业爱岗敬业演讲稿
2014/09/04 职场文书
2014入党积极分子批评与自我批评思想汇报
2014/09/20 职场文书
《追风筝的人》:人心中的成见是座大山,但请不忘初心
2019/11/15 职场文书
《金肉人》米特&《航海王》阿鹤声优松岛实因胰脏癌去世 享寿81岁
2022/04/13 日漫
JavaScript正则表达式实现注册信息校验功能
2022/05/30 Java/Android