js跨域

jsonp

原理:
JSONP 利用 <script>元素的这个开放策略,网页可以得到从其他来源动态产生的JSON数据,而这种使用模式就是所谓的 JSONP。用JSONP抓到的数据并不是JSON,而是任意的JavaScript,用 JavaScript解释器运行而不是用JSON解析器解析。

<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>

远程的remote.js

localHandler({"result":"我是远程js带来的数据"});

我本地请求

<!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>

请求flightResult.aspx获取的数据

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

调用的url中传递了一个code参数,告诉服务器我要查的是CA1998次航班的信息,而callback参数则告诉服务器,我的本地回调函数叫做flightHandler,所以请把查询结果传入这个函数中进行调用。

劣势: 支持get 安全性不高 (可以通过动态生成jsonp解决)

与ajax的区别
但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加<script>标签来调用服务器提供的js脚本。

cors

document.domain+iframe(适用于主域名相同的情况)

在域名为http://server.example.com中的a.html

document.domain = 'example.com';
var $iframe = document.createElement('iframe');
$iframe.src = 'server.child.example.com/b.html';
$iframe.style.display = 'none';
document.body.appendChild($iframe);
$iframe.onload = function(){
    var doc = $iframe.contentDocument || $iframe.contentWindow.document;
    //在这里操作doc,也就是操作b.html
    $iframe.onload = null;
};

在域名为http://server.child.example.com中的b.html

document.domain = 'example.com'

这种形式方便归方便,但也有其方便带来的隐患

  • 安全性,当一个站点被攻击后,另一个站点会引起安全漏洞。

  • 若页面中引入多个iframe,要想操作所有iframe,domain需要全部设置成一样的。

HTML5中的postMessage

postMessage隶属于html5,但是它支持IE8+和其他浏览器,可以实现同域传递,也能实现跨域传递。它包括发送消息postMessage和接收消息message功能。

postMessage调用语法如下

otherWindow.postMessage(message, targetOrigin, [transfer]);

  • otherWindow : 其他窗口的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames。
  • message : 将要发送到其他 window的数据,类型为string或者object。
  • targetOrigin : 通过窗口的origin属性来指定哪些窗口能接收到消息事件,其值可以是字符串"*"(表示无限制)或者一个URI。
  • transfer (可选) : 一串和message 同时传递的 Transferable 对象。

接收消息message 的属性有:

  • data :从其他 window 中传递过来的数据。
  • origin :调用 postMessage 时消息发送方窗口的 origin 。
  • source :对发送消息的窗口对象的引用。

示例如下:域名http://127.0.0.1:9000页面A通过iframe嵌入了http://127.0.0.1页面B,接下来页面A将通过postMessage对页面B进行数据传递,页面B将通过message属性接收页面A的数据

页面A发送消息代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>页面A</title>
</head>
<body>
    <h1>hello jsonp</h1>
    <iframe src="http://127.0.0.1/b.html" id="iframe"></iframe>
</body>
</html>
<script>
window.onload = function() {  
    var $iframe = document.getElementById('iframe');  
    var targetOrigin = "http://127.0.0.1";  
    $iframe.contentWindow.postMessage('postMessage发送消息', targetOrigin);  
}; 
</script>

页面B接收消息代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>页面B</title>
</head>
<body>
    <h1>hello jsonp</h1>
</body>
</html>
<script>
var onmessage = function (event) {
  var data = event.data;    //消息
  var origin = event.origin; //消息来源地址
  var source = event.source; //源Window对象
  if(origin === "http://127.0.0.1:9000"){
    console.log(data, origin, source);
  }
};
// 事件兼容简单处理
if (window.addEventListener) {
  window.addEventListener('message', onmessage, false);
}
else if (window.attachEvent) {
  window.attachEvent('onmessage', onmessage);
}
else {
  window.onmessage = onmessage;
}
</script>

运行结果如下

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Section1、为什么要跨域? 自古以来(1995年起),为了用户的信息安全,浏览器就引入了同源策略。那么同源策...
    qhaobaba阅读 406评论 0 0
  • Section1、为什么要跨域? 自古以来(1995年起),为了用户的信息安全,浏览器就引入了同源策略。那么同源策...
    不去解释阅读 599评论 0 0
  • 0. 前言 说到AJAX就会不可避免的面临两个问题。 AJAX以何种格式来交换数据? 第二个是跨域的需求如何解决?...
    公子七阅读 23,704评论 7 67
  • JavaScript是一种在Web开发中经常使用的前端动态脚本技术。在JavaScript中,有一个很重要的...
    西瓜w阅读 1,819评论 0 1
  • 感恩方姐组织日行一善群到养老院送温暖的活动。看到那些慈善的老人虽然远离家人,但是在敬老院都生活得很好,身体也很健康...
    武丹yoyo阅读 196评论 0 1