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实现跨浏览器获取鼠标按键的值
Apr 08 Javascript
JS特殊函数(Function()构造函数、函数直接量)区别介绍
May 19 Javascript
javascript阻止浏览器后退事件防止误操作清空表单
Nov 22 Javascript
原生态js,鼠标按下后,经过了那些单元格的简单实例
Aug 11 Javascript
ajax接收后台数据在html页面显示
Feb 19 Javascript
HTML5实现微信拍摄上传照片功能
Apr 21 Javascript
Bootstrap Table使用整理(四)之工具栏
Jun 09 Javascript
JS+Ajax实现百度智能搜索框
Aug 04 Javascript
微信小程序template模板实例详解
Oct 27 Javascript
Mac中安装nvm的教程分享
Dec 11 Javascript
微信小程序动态增加按钮组件
Sep 14 Javascript
JavaScript判断对象和数组的两种方法
May 31 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
Banner程序
2006/10/09 PHP
PHP 日志缩略名的创建函数代码
2010/05/26 PHP
Can't create/write to file 'C:\WINDOWS\TEMP\...MYSQL报错解决方法
2011/06/30 PHP
PHP实现简单数字分页效果
2015/07/26 PHP
php关键字仅替换一次的实现函数
2015/10/29 PHP
Symfony2在Nginx下的配置方法图文教程
2016/02/04 PHP
CI框架中类的自动加载问题分析
2016/11/21 PHP
PHP获取真实客户端的真实IP
2017/03/07 PHP
Yii 框架使用Forms操作详解
2020/05/18 PHP
Prototype使用指南之hash.js
2007/01/10 Javascript
IE浏览器兼容Firefox的JS脚本的代码
2008/10/23 Javascript
NodeJS学习笔记之(Url,QueryString,Path)模块
2015/01/13 NodeJs
JQuery节点元素属性操作方法
2015/06/11 Javascript
JQuery工具函数汇总
2015/06/15 Javascript
JS实现关闭当前页而不弹出提示框的方法
2016/06/22 Javascript
JS 实现导航菜单中的二级下拉菜单的几种方式
2016/10/31 Javascript
利用js获取下拉框中所选的值
2016/12/01 Javascript
JavaScript实现鼠标点击导航栏变色特效
2017/02/08 Javascript
详解使用nvm安装node.js
2017/07/18 Javascript
推荐VSCode 上特别好用的 Vue 插件之vetur
2017/09/14 Javascript
JavaScript大数相加相乘的实现方法实例
2020/10/18 Javascript
Python多继承顺序实例分析
2018/05/26 Python
Python代码块批量添加Tab缩进的方法
2018/06/25 Python
Python爬虫之正则表达式的使用教程详解
2018/10/25 Python
TFRecord格式存储数据与队列读取实例
2020/01/21 Python
如何对python的字典进行排序
2020/06/19 Python
Django model class Meta原理解析
2020/11/14 Python
关于css中margin的值和垂直外边距重叠问题
2020/10/27 HTML / CSS
Tea Collection官网:一家位于旧金山的童装公司
2020/08/07 全球购物
钳工实习自我鉴定
2013/09/19 职场文书
2014年保密工作总结
2014/11/22 职场文书
2014年党委工作总结
2014/11/22 职场文书
大二学年个人总结
2015/03/03 职场文书
2019终止劳动合同协议书最新范本!
2019/07/09 职场文书
读《工匠精神》有感:热爱工作,精益求精
2019/12/28 职场文书
Linux系统下安装PHP7.3版本
2021/06/26 PHP