常见的javascript跨域通信方法


Posted in Javascript onDecember 31, 2015

本文主要介绍几种常见的javascript跨域通信方法。首先讲解一下JSONP。
1、JSONP
JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML 的<script> 元素是一个例外。利用 <script> 元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON 资料,而这种使用模式就是所谓的 JSONP。用 JSONP 抓到的资料并不是JSON,而是任意的JavaScript,用 JavaScript 直译器执行而不是用 JSON 解析器解析。
下面我们来介绍下JSONP的具体实现。
我们知道,哪怕跨域js文件中的代码(当然指符合web脚本安全策略的),web页面也是可以无条件执行的。远程服务器remoteserver.com根目录下有个remote.js文件代码如下:
alert('我是远程文件'); 
本地服务器localserver.com下有个jsonp.html页面代码如下:

<!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></title> 
 <script type="text/javascript" src="http://remoteserver.com/remote.js"></script> 
</head> 
<body> 
 
</body> 
</html>

毫无疑问,页面将会弹出一个提示窗体,显示跨域调用成功。

现在我们在jsonp.html页面定义一个函数,然后在远程remote.js中传入数据进行调用。jsonp.html页面代码如下:

<!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></title> 
 <script type="text/javascript"> 
 var localHandler = function(data){ 
  alert('我是本地函数,可以被跨域的remote.js文件调用,远程js带来的数据是:' + data.result); 
 }; 
 </script> 
 <script type="text/javascript" src="http://remoteserver.com/remote.js"></script> 
</head> 
<body> 
 
</body> 
</html>

remote.js文件代码如下:
localHandler({"result":"我是远程js带来的数据"}); 
成功运行,看来跨域远程获取数据的目的实现了,但是又一个问题出现了,我怎么让远程js知道它应该调用的本地函数叫什么名字呢?这时我们就需要将服务端提供的js脚本动态生成就行了,调用者可用通过传参告诉服务端自己需要什么函数,jsonp.html的代码如下:

<!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></title> 
 <script type="text/javascript"> 
 // 得到航班信息查询结果后的回调函数 
 var flightHandler = function(data){ 
  alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。'); 
 }; 
 // 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码) 
 var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler"; 
 // 创建script标签,设置其属性 
 var script = document.createElement('script'); 
 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,所以请把查询结果传入这个函数中进行调用。这个叫做flightResult.aspx的页面生成了一段这样的代码提供给jsonp.html(服务端的实现这里就不演示了,与你选用的语言无关,说到底就是拼接字符串):

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

传递给flightHandler函数的是一个json,它描述了航班的基本信息。运行一下页面,成功弹出提示窗口,jsonp的执行全过程顺利完成!
但是JSONP存在一点问题,就是由远程服务端负责包装json数据,并调用命名函数,这种方式存在安全隐患,在使用JSONP时,必须完全信任服务端所提供的数据,恶意脚本就可以直接接管我们的应用。所以接下来我们要介绍一种别的方式,来避免这种安全隐患。
2、CORS
CORS(Cross OriginResource Sharing,跨源资源共享)实现了跨源XMLHttpRequests,跨源HTTP请求包括一个Origin头部,它为服务器提供HTTP请求的源信息。头部由浏览器保护,不能被应用程序代码更改。这种方式远比评估外部输入的方式安全。
以前的ajax只能同源请求,现在通过XMLHttpRequests二级,可以进行跨域请求。假设我们页面或者应用已在 http://www.test1.com 上了,而我们打算从 http://www.test2.com 请求提取数据。一般情况下,如果我们直接使用 AJAX 来请求将会失败,浏览器也会返回“源不匹配”的错误,"跨域"也就以此由来。
利用 CORS,http://www.test2.com 只需添加一个标头,就可以允许来自 http://www.test1.com 的请求。php代码如下:

header("Access-Comtrol-Allow-Origin:*");<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>

其中*表示允许任何域向我们的服务端提交请求。也可以设置指定的域名,代码如下:

header("Access-Control-Allow-Origin:http://www.test2.com");

设置好头信息之后,其他域就可以进行请求了。
        使用"跨域资源共享"的前提,是浏览器必须支持这个功能,而且服务器端必须同意这种"跨域"。如果能够满足上面的条件,则代码的写法与不跨域的请求完全一样。
xhr.open('GET', ' http://www.test2.com '); 
 接下来介绍另外一种实时通信方式:
3、Cross-document messaging
跨文档信息通信。使用这个功能,只要获取到网页所在窗口对象的实例,不仅同原的web网页可以互相通信,也可以实现跨域通信。要想接受从其他窗口发送来的信息,必须对窗口对象的onmessage事件进行监听,其他窗口可以通过postmessage方法来传递数据,该方法使用两个参数:第一个参数为所发送的消息文本,但也可以是任何js对象,第二个参数为接收消息的对象窗口的url地址。
下面进行试验,主页面index.html代码如下:

<!DOCTYPE html> 
<html> 
 <head> 
  <meta charset="utf-8"> 
  <title></title> 
 </head> 
<script type="text/javascript"> 
 function sendIt(){ 
  document.getElementById("otherPage").contentWindow 
  .postMessage(//向子窗口发出请求 
   document.getElementById("message").value,//值 
   "http://127.0.0.1:8020"//目标域 
  ) 
 } 
</script> 
 <body> 
  <iframe src="http://127.0.0.1:8020/test2/JS/jstest/Cross-document-messaging/other.html" id="otherPage" width="" height=""></iframe> 
  <br /><br /> 
  <input type="text" name="message" id="message" value="" /> 
  <input type="button" name="" id="" value="发送跨域消息" onclick="sendIt();" /> 
 </body> 
</html>

 窗口所引用页面other.html代码如下:

<!DOCTYPE html> 
<html> 
 <head> 
  <meta charset="utf-8"> 
  <title></title> 
<script type="text/javascript"> 
 window.addEventListener("message",function(event){//通过onmessage监听 
  //将从父窗口传来的数据展现出来 
  document.getElementById("content").innerHTML+=event.data+"<br>"; 
 },false); 
</script> 
 </head> 
 <body> 
  信息来自于另外一个域 
  <div id="content"> 
    
  </div> 
 </body> 
</html>

试验结果如下:

常见的javascript跨域通信方法

可以看到在81端口服务器中的index.html和8020端口的服务器中的other.html进行的通信。
完整代码如下:

<!DOCTYPE html>
<html>
 <head>
 <meta charset="utf-8">
 <title></title>
 </head>
<script type="text/javascript">
 function sendIt(){
 document.getElementById("otherPage").contentWindow
 .postMessage(//向子窗口发出请求
 document.getElementById("message").value,//值
 "http://127.0.0.1:8020"//目标域
 )
 }
</script>
 <body>
 <iframe src="http://127.0.0.1:8020/test2/JS/jstest/Cross-document-messaging/other.html" id="otherPage" width="" height=""></iframe>
 <br /><br />
 <input type="text" name="message" id="message" value="" />
 <input type="button" name="" id="" value="发送跨域消息" onclick="sendIt();" />
 </body>
</html>

CrossDocumentMessaging_index.html

<!DOCTYPE html>
<html>
 <head>
 <meta charset="utf-8">
 <title></title>
<script type="text/javascript">
 window.addEventListener("message",function(event){//通过onmessage监听
 //将从父窗口传来的数据展现出来
 document.getElementById("content").innerHTML+=event.data+"<br>";
 },false);
</script>
 </head>
 <body>
 信息来自于另外一个域
 <div id="content">
 
 </div>
 </body>
</html>

以上就是本文的全部内容,希望对大家了解熟悉常见的javascript跨域通信方法有所帮助。

Javascript 相关文章推荐
Javascript客户端脚本的设计和应用
Aug 21 Javascript
关于Blog顶部的滚动导航条代码
Sep 25 Javascript
jquery简单体验
Jan 10 Javascript
JQuery Ajax 跨域访问的解决方案
Mar 12 Javascript
js中方法重载如何实现?以及函数的参数问题
Aug 01 Javascript
JS实现Enter键跳转及控件获得焦点
Aug 12 Javascript
JS实现拖动示例代码
Nov 01 Javascript
js中的事件捕捉模型与冒泡模型实例分析
Jan 10 Javascript
jquery点击缩略图切换视频播放特效代码分享
Sep 15 Javascript
巧方法 JavaScript获取超链接的绝对URL地址
Jun 14 Javascript
jQuery Tree Multiselect使用详解
May 02 jQuery
微信小程序登陆注册功能的实现代码
Dec 10 Javascript
javascript实现input file上传图片预览效果
Dec 31 #Javascript
分享几种比较简单实用的JavaScript tabel切换
Dec 31 #Javascript
jQuery+ajax实现文章点赞功能的方法
Dec 31 #Javascript
jQuery实现的超简单点赞效果实例分析
Dec 31 #Javascript
jQuery实现的给图片点赞+1动画效果(附在线演示及demo源码下载)
Dec 31 #Javascript
jQuery实现的点赞随机数字显示动画效果(附在线演示与demo源码下载)
Dec 31 #Javascript
AngularJS中实现显示或隐藏动画效果的方式总结
Dec 31 #Javascript
You might like
php实现从上传文件创建缩略图的方法
2015/04/02 PHP
JSON两种结构之对象和数组的理解
2016/07/19 PHP
php版微信小店API二次开发及使用示例
2016/11/12 PHP
利用cookie记住背景颜色示例代码
2013/11/04 Javascript
jq实现酷炫的鼠标经过图片翻滚效果
2014/03/12 Javascript
JavaScript将取代AppleScript?
2014/09/18 Javascript
javascript连续赋值问题
2015/07/08 Javascript
js格式化输入框内金额、银行卡号
2016/02/01 Javascript
javascript中异常处理案例(推荐)
2016/10/03 Javascript
js HTML5手机刮刮乐代码
2020/09/29 Javascript
如何在js代码中消灭for循环实例详解
2018/07/29 Javascript
JS 音频可视化插件Wavesurfer.js的使用教程
2018/10/31 Javascript
详解vue-cli 脚手架 安装
2019/04/16 Javascript
javascript中的数据类型检测方法详解
2019/08/07 Javascript
Vue 实现一个简单的鼠标拖拽滚动效果插件
2020/12/10 Vue.js
Python实现计算文件夹下.h和.cpp文件的总行数
2015/04/23 Python
Python 常用string函数详解
2016/05/30 Python
详解Python3网络爬虫(二):利用urllib.urlopen向有道翻译发送数据获得翻译结果
2019/05/07 Python
python 根据字典的键值进行排序的方法
2019/07/24 Python
Python queue队列原理与应用案例分析
2019/09/27 Python
Python OrderedDict的使用案例解析
2019/10/25 Python
python 统计文件中的字符串数目示例
2019/12/24 Python
django项目中使用云片网发送短信验证码的实现
2021/01/19 Python
canvas像素画板的实现代码
2018/11/21 HTML / CSS
俄罗斯披萨、寿司和面食送货到家服务:2 Берега
2019/12/15 全球购物
公司道歉信范文
2014/01/09 职场文书
创业计划书的写作技巧及要点
2014/01/31 职场文书
市场营销个人求职信范文
2014/02/02 职场文书
学习教师敬业奉献模范事迹材料思想汇报
2014/09/19 职场文书
单位租车协议书
2015/01/29 职场文书
邀请函样本
2015/02/02 职场文书
幼儿园中班个人总结
2015/02/28 职场文书
优秀团员自我评价
2015/03/10 职场文书
旅行社计调工作总结
2015/08/12 职场文书
党风廉政建设心得体会(2016最新版)
2016/01/22 职场文书
《废话连篇——致新手》——chinapizza
2022/04/05 无线电