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 相关文章推荐
幻宇的层模拟窗口效果-提供演示和下载
Jan 20 Javascript
javascript中字符串的定义示例代码
Dec 19 Javascript
jQuery实现的左右移动焦点图效果
Jan 14 Javascript
详解javascript传统方法实现异步校验
Jan 22 Javascript
JavaScript实现数据类型的相互转换
Mar 06 Javascript
Bootstrap 3.x打印预览背景色与文字显示异常的解决
Nov 06 Javascript
JS中from 表单序列化提交的代码
Jan 20 Javascript
详解Js中的模块化是如何实现的
Oct 18 Javascript
React 使用browserHistory项目访问404问题解决
Jun 01 Javascript
angularjs http与后台交互的实现示例
Dec 21 Javascript
JavaScript模板引擎原理与用法详解
Dec 24 Javascript
JavaScript Array对象使用方法解析
Sep 24 Javascript
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 cache类代码(php数据缓存类)
2010/04/15 PHP
php摘要生成函数(无乱码)
2012/02/04 PHP
PHP实现QQ登录实例代码
2016/01/14 PHP
thinkPHP中配置的读取与C方法详解
2016/12/05 PHP
laravel实现批量更新多条记录的方法示例
2017/10/22 PHP
Jquery时间验证和转换工具小例子
2013/07/01 Javascript
JS实现在网页中弹出一个输入框的方法
2015/03/03 Javascript
jQuery中 attr() 方法使用小结
2015/05/03 Javascript
jQuery实现自动输入email、时间和域名的方法
2016/08/24 Javascript
解决node.js安装包失败的几种方法
2016/09/02 Javascript
深入理解vue中的$set
2017/06/01 Javascript
javascript 取小数点后几位几种方法总结
2017/08/02 Javascript
nodejs实现简单的gulp打包
2017/12/21 NodeJs
Angular异步变同步处理方法
2018/08/13 Javascript
vue使用Proxy实现双向绑定的方法示例
2019/03/20 Javascript
微信小程序利用Canvas绘制图片和竖排文字详解
2019/06/25 Javascript
Vue使用v-viewer实现图片预览
2020/10/21 Javascript
探索node之事件循环的实现
2020/10/30 Javascript
跟老齐学Python之大话题小函数(1)
2014/10/10 Python
python调用机器喇叭发出蜂鸣声(Beep)的方法
2015/03/23 Python
用pickle存储Python的原生对象方法
2017/04/28 Python
利用PyInstaller将python程序.py转为.exe的方法详解
2017/05/03 Python
Python编程求解二叉树中和为某一值的路径代码示例
2018/01/04 Python
实用自动化运维Python脚本分享
2018/06/04 Python
Python基于百度云文字识别API
2018/12/13 Python
基于python实现把图片转换成素描
2019/11/13 Python
使用Python爬取弹出窗口信息的实例
2020/03/14 Python
CSS3文本换行word-wrap解决英文文本超过固定宽度不换行
2013/10/10 HTML / CSS
新年联欢会主持词
2014/03/27 职场文书
《神奇的克隆》教学反思
2014/04/10 职场文书
党的群众路线教育实践活动教师自我剖析材料
2014/10/09 职场文书
给客户的检讨书
2014/12/21 职场文书
汽车转让协议书
2015/01/29 职场文书
公司更名通知函
2015/04/24 职场文书
调解协议书范本
2016/03/21 职场文书
redis数据结构之压缩列表
2022/03/21 Redis