常见的javascript跨域通信方法
作者:bea
本文主要介绍几种常见的javascript跨域通信方法。首先讲解一下JSONP。 1、JSONP JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML 的<script> 元素是一个例外。利用 <script> 元素的这个开放策略,网页可
本文主要介绍几种常见的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>
试验结果如下:
可以看到在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跨域通信方法有所帮助。
有用 | 无用
<!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>
试验结果如下:
可以看到在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跨域通信方法有所帮助。
有用 | 无用
猜你喜欢
您可能感兴趣的文章:
- 理解jquery事件冒泡
- 实例讲解避免javascript冲突的方法
- 详解js中class的多种函数封装方法
- js中利用tagname和id获取元素的方法
- 信息页文内画中画广告js实现代码(文中加载广告方式)
- 基于javascript实现简单计算器功能
- 详解Javascript事件驱动编程
- 基于javascript实现仿百度输入框自动匹配功能
- js实现搜索框关键字智能匹配代码
- javascript合并表格单元格实例代码
- JS Array.slice 截取数组的实现方法
- jquery实现简单的全选和反选功能
- 基于Javascript实现弹出页面效果
- 基于jQuery实现点击弹出层实例代码
- 基于jQuery实现返回顶部实例代码
- 基于JavaScript实现定时跳转到指定页面
- Javascript获取数组中的最大值和最小值的方法汇总
- 实例详解JavaScript获取链接参数的方法
- 快速学习AngularJs HTTP响应拦截器