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 相关文章推荐
关于UTF-8的客户端用AJAX方式获取GB2312的服务器端乱码问题的解决办法
Nov 30 Javascript
纯js代码实现未知宽高的元素在指定元素中垂直水平居中显示
Sep 12 Javascript
jquery form表单获取内容以及绑定数据
Feb 24 Javascript
基于JS实现导航条之调用网页助手小精灵的方法
Jun 17 Javascript
解析浏览器端的AJAX缓存机制
Jun 21 Javascript
微信小程序 this和that详解及简单实例
Feb 13 Javascript
vue.js实例对象+组件树的详细介绍
Oct 20 Javascript
OkHttp踩坑随笔为何 response.body().string() 只能调用一次
Jan 08 Javascript
泛谈JS逻辑判断选择器 || &amp;&amp;
May 24 Javascript
对Layer弹窗使用及返回数据接收的实例详解
Sep 26 Javascript
微信小程序顶部导航栏可滑动并选中放大
Dec 05 Javascript
ant design vue中日期选择框混合时间选择器的用法说明
Oct 27 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数组函数序列之array_combine() - 数组合并函数使用说明
2011/10/29 PHP
浅谈PHP强制类型转换,慎用!
2013/06/06 PHP
php实现统计邮件大小的方法
2013/08/06 PHP
PHP简单实现“相关文章推荐”功能的方法
2014/07/19 PHP
javascript 处理HTML元素必须避免使用的一种方法
2009/07/30 Javascript
js 多浏览器分别判断代码
2010/04/01 Javascript
jquery中的事件处理详细介绍
2013/06/24 Javascript
JS简单的图片放大缩小的两种方法
2013/11/11 Javascript
jQuery获得document和window对象宽度和高度的方法
2015/03/25 Javascript
javascript创建动态表单的方法
2015/07/25 Javascript
JS组件Bootstrap Select2使用方法解析
2016/05/30 Javascript
js 自带的sort() 方法全面了解
2016/08/16 Javascript
windows 下安装nodejs 环境变量设置
2017/02/02 NodeJs
vue+webpack 打包文件 404 页面空白的解决方法
2018/02/28 Javascript
bootstrap treeview 树形菜单带复选框及级联选择功能
2018/06/08 Javascript
angularjs使用div模拟textarea文本框的方法
2018/10/02 Javascript
Vue列表渲染的示例代码
2018/11/01 Javascript
vue-music 使用better-scroll遇到轮播图不能自动轮播问题
2018/12/03 Javascript
vue的for循环使用方法
2019/02/12 Javascript
解析原来浏览器原生支持JS Base64编码解码
2019/08/12 Javascript
Nodejs技巧之Exceljs表格操作用法示例
2019/11/06 NodeJs
node运行js获得输出的三种方式示例详解
2020/07/02 Javascript
[00:59]DOTA2荣耀之路1:Doom is back!weapon X!
2018/05/22 DOTA
python中列表元素连接方法join用法实例
2015/04/07 Python
Python中的自省(反射)详解
2015/06/02 Python
使用Python绘制图表大全总结
2017/02/11 Python
对Python 文件夹遍历和文件查找的实例讲解
2018/04/26 Python
在python中做正态性检验示例
2019/12/09 Python
联想香港官方网站及网店:Lenovo香港
2018/04/13 全球购物
Tretorn美国官网:瑞典外套和鞋类品牌,抵御风雨
2018/07/19 全球购物
保险专业大专生求职信
2013/10/26 职场文书
市场推广策划方案
2014/06/02 职场文书
读群众路线的心得体会
2014/09/03 职场文书
2014年培训工作总结范文
2014/11/27 职场文书
满月酒邀请函
2015/01/30 职场文书
亮剑观后感300字
2015/06/05 职场文书