同源策略

所谓的同源策略,指的是浏览器对不同源的脚本或者文本访问方式进行的限制。
所谓同源,就是指两个页面具有相同的协议,主机(也常说域名),端口,三个要素缺一不可。
同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。
如果一个用户在登陆一个网站之后又去访问其他网站,如果其他网站可以读取上一个网站的cookie,就会导致个人信息泄露。

限制范围

随着互联网的发展,"同源政策"越来越严格。目前,如果非同源,共有三种行为受到限制:
1、cookie、localstorage、indexDB(IndexedDB 是一种低级API,用于客户端存储大量结构化数据(包括, 文件/ blobs)。该API使用索引来实现对该数据的高性能搜索。)无法读取
2、DOM无法获得。
3、AJAX请求不能发送。

规避措施

1、cookie

Cookie是服务器写入浏览器的一小段信息,只有同源的网页才能共享,但是两个网页只有一级域名相同,只是二级域名不同,浏览器允许通过设置document.domain共享Cookie。
举例来说,A,http://w1.example.com/a.html B,http://w2.example.com/b.html,那么只要设置相同的document.domain,两个网页就可以共享Cookie。
document.domain='example.com'
A通过脚本设置一个Cookie:document.cookie='text=hello'
B网页就可以读到这个Cookie。var allCookie=document.cookie;
  • 这种方法只适用于Cookie和iframe窗口,LocalStorage和IndexDB无法通过这种方法,规避同源政策。需要使用PostMessage API。另外,服务器也可以在设置Cookie的所属域名为一级域名,比如:.example.com。

    Set-Cookie:key=value;domain=.example.com; path=/

    这样的话,二级域名和三级域名不用做任何设置都可以读取这个Cookie。

2、iframe

如果两个网页不同源,就无法拿到对方的DOM。典型的例子是iframe窗口和window.open方法打开的窗口,他们与父窗口无法通信。
比如,父窗口运行下面的命令,如果iframe不同源就会导致错误,document.getElementById('myIframe').contentWindow.document,上面的命令中,父窗口想获取子窗口的DOM,因为跨源导致报错。反之亦然。
如果两个完全不同源的网站,目前有三种方法,可以解决跨域窗口的通信问题。
1、片段识别符(fragment identifier)
2、window.name
3、跨文档通信API(Cross-document messaging)
  • 片段识别符

    指的是URL的#号后面的部分,比如 http://example.com/x.html#fragment的#fragment。如果只是改变片段标识符,页面不会重新刷新。父窗口可以把信息,写入子窗口的片段标识符。

    var src=originURL+'#'+data;

    document.getElementById('myIFrame')

    子窗口通过监听hashchange事件得到通知。

    window.onhashchange=checkMessage;

    function checkMessage(){

    var message=window.location.hash;

    }

    同样的,子窗口也可以改变父窗口的片段标识符。

    parent.location.href=target+'#'+data;

  • window.name

    浏览器窗口有window.name属性,这个属性的最大特点是,无论是否同源,只要在同一个窗口,前一个网页设置了这个属性,后一个网页就可以读取他。

    父窗口先打开一个子窗口,载入一个不同源的网页,该网页将信息写入window.name属性。

    window.name = data;

    接着,子窗口跳回一个与主窗口同域的网址。

    location = 'http://parent.url.com/xxx.html';

    然后,主窗口就可以读取子窗口的window.name了。

    var data = document.getElementById('myFrame').contentWindow.name;

    这种方法的优点是,window.name容量很大,可以放置非常长的字符串;缺点是必须监听子窗口window.name属性的变化,影响网页性能。

  • window.postMessage

    上面两种方法都属于破解,HTML5为了解决这个问题,引入了一个全新的API:跨文档通信 API(Cross-document messaging)。

    这个API为window对象新增了一个window.postMessage方法,允许跨窗口通信,不论这两个窗口是否同源。

    举例来说,父窗口http://aaa.com向子窗口http://bbb.com发消息,调用postMessage方法就可以了。

    var popup = window.open('http://bbb.com', 'title');

    popup.postMessage('Hello World!', 'http://bbb.com');

    postMessage方法的第一个参数是具体的信息内容,第二个参数是接收消息的窗口的源(origin),即"协议 + 域名 + 端口"。也可以设为*,表示不限制域名,向所有窗口发送。

    子窗口向父窗口发送消息的写法类似。

    window.opener.postMessage('Nice to see you', 'http://aaa.com');

    父窗口和子窗口都可以通过message事件,监听对方的消息。

    window.addEventListener('message', function(e) {

    console.log(e.data);

    },false);

    message事件的事件对象event,提供以下三个属性。

    event.source:发送消息的窗口

    event.origin: 消息发向的网址

    event.data: 消息内容

    下面的例子是,子窗口通过event.source属性引用父窗口,然后发送消息。

    window.addEventListener('message', receiveMessage);
function receiveMessage(event) {
event.source.postMessage('Nice to see you!', '*');
}
event.origin属性可以过滤不是发给本窗口的消息。
    window.addEventListener('message', receiveMessage);
function receiveMessage(event) {
if (event.origin !== 'http://aaa.com') return;
if (event.data === 'Hello World') {
event.source.postMessage('Hello', event.origin);
} else {
console.log(event.data);
}
}

3、LocalStorage

通过window.postMessage,读写其他窗口的 LocalStorage 也成为了可能。
下面是一个例子,主窗口写入iframe子窗口的localStorage。
window.onmessage = function(e) {
if (e.origin !== 'http://bbb.com') {
return;
}
var payload = JSON.parse(e.data);
localStorage.setItem(payload.key, JSON.stringify(payload.data));
};
上面代码中,子窗口将父窗口发来的消息,写入自己的LocalStorage。
父窗口发送消息的代码如下。
var win = document.getElementsByTagName('iframe')[0].contentWindow;
var obj = { name: 'Jack' };
win.postMessage(JSON.stringify({key: 'storage', data: obj}), 'http://bbb.com');
加强版的子窗口接收消息的代码如下。
      if (e.origin !== 'http://bbb.com') return;
var payload = JSON.parse(e.data);
switch (payload.method) {
case 'set':
localStorage.setItem(payload.key, JSON.stringify(payload.data));
break;
case 'get':
var parent = window.parent;
var data = localStorage.getItem(payload.key);
parent.postMessage(data, 'http://aaa.com');
break;
case 'remove':
localStorage.removeItem(payload.key);
break;
}
};
加强版的父窗口发送消息代码如下。
    var win = document.getElementsByTagName('iframe')[0].contentWindow;
var obj = { name: 'Jack' };
// 存入对象
win.postMessage(JSON.stringify({key: 'storage', method: 'set', data: obj}), 'http://bbb.com');
// 读取对象
win.postMessage(JSON.stringify({key: 'storage', method: "get"}), "*");
window.onmessage = function(e) {
if (e.origin != 'http://aaa.com') return;
// "Jack"
console.log(JSON.parse(e.data).name);
};

JavaScript中的跨域详解(一)的更多相关文章

  1. JavaScript中的跨域详解(二)

    4.AJAX 同源政策规定,AJAX请求只能发给同源的网址,否则就报错. 除了架设服务器代理(浏览器请求同源服务器,再由后者请求外部服务),有三种方法规避这个限制. JSONP WebSocket C ...

  2. javascript中=、==、===区别详解

    javascript中=.==.===区别详解今天在项目开发过中发现在一个小问题.在判断n==""结果当n=0时 n==""结果也返回了true.虽然是个小问题 ...

  3. JavaScript中return的用法详解

    JavaScript中return的用法详解 最近,跟身边学前端的朋友了解,有很多人对函数中的this的用法和指向问题比较模糊,这里写一篇博客跟大家一起探讨一下this的用法和指向性问题. 1定义 t ...

  4. javascript 中合并排序算法 详解

    javascript 中合并排序算法 详解 我会通过程序的执行过程来给大家合并排序是如何排序的...  合并排序代码如下: <script type="text/javascript& ...

  5. javascript中的this作用域详解

    javascript中的this作用域详解 Javascript中this的指向一直是困扰我很久的问题,在使用中出错的机率也非常大.在面向对象语言中,它代表了当前对象的一个引用,而在js中却经常让我觉 ...

  6. JavaScript中this的用法详解

    JavaScript中this的用法详解 最近,跟身边学前端的朋友了解,有很多人对函数中的this的用法和指向问题比较模糊,这里写一篇博客跟大家一起探讨一下this的用法和指向性问题. 1定义 thi ...

  7. JavaScript中的跨域

    跨域是什么 跨域就是指从一个域名的网页去请求另一个域名的资源,因为JavaScript同源策略的限制,资源无法获取.比如从www.baidu.com 页面去请求 www.google.com 的资源, ...

  8. 跨域详解之jsonp,底层的实现原理

    分享一下跨域,不仅是因为现在的工作中遇到的越来越多,而且在面试中也经常被问到. 那么什么是跨域呢,我们来看官方给出的解释:浏览器不能执行其他网站的脚本.它是由浏览器的同源策略造成的(所谓同源是指,域名 ...

  9. JavaScript中数组Array方法详解

    ECMAScript 3在Array.prototype中定义了一些很有用的操作数组的函数,这意味着这些函数作为任何数组的方法都是可用的. 1.Array.join()方法 Array.join()方 ...

随机推荐

  1. (转)MapReduce Design Patterns(chapter 6 (part 2))(十二)

    Chain Folding 这是对job 链的一种优化.基本上是一种大体规则:每条记录都会提交给多个mapper,或者给reducer然后给mapper.这种综合处理方法会节省很多读文件和传输数据的时 ...

  2. d3.js(v5.7)力导向图(关系图谱)

    先上图,后面再一一解释: ok,为了方便理解,这里我就没有用之前封装的automatch函数来将数据和节点匹配了,如果你对enter(),exit()函数还不是很理解的话,请移步至我之前写的<n ...

  3. 用css和php脚本来使得poscms的list标签顺利输出记录

    每次拿到前端给的页面,都会有意想不到的惊喜,因为他们给的页面总是不能很好地契合poscms的模板标签 输出规范,这时候就需要动点脑筋去解决问题了. 拿前两天拿到的一类(对,你没看错,是一类)页面来说吧 ...

  4. Windows7下PHP 7.1搭建开发环境

    引言: PHP天生就是用来解决互联网时代的Web语言问题的专业工具,本文将记录在windows上搭建PHP的过程以及其中碰到的问题. 配置版本信息 OS: Windows 7 PHP: 7.1.7-n ...

  5. Android Studio3.0 Kotlin工程问题集

    问题1: 新建支持Kotlin的Android项目,卡在"Resolve dependency :classpath" 解决分析: 一般碰到"Resolve depend ...

  6. JMter中添加断点和关联

    一.            断点 断言是什么呢,它是用来检查返回结果对不对的. 用来验证结果是否正确,如果正确的话,就代表这个请求的返回是正确的,如果没有的话就代表这个请求的结果和我们预期的不一致,这 ...

  7. ranch分析学习(四)

    经过的前面的梳理,整个ranch框架的结构,大致有了一个清晰的脉络,即使我说的不是很清楚大家也基本能阅读懂源码.下面我继续分析剩下的的几个文件. 7.ranch_transport.erl 这个文件是 ...

  8. 白话machine learning之Loss Function

    转载自:http://eletva.com/tower/?p=186 有关Loss Function(LF),只想说,终于写了 一.Loss Function 什么是Loss Function?wik ...

  9. HihoCoder 1063 : 缩地 树形DP第二题(对象 边)

    时间限制:12000ms 单点时限:1000ms 内存限制:256MB 描述 编织者是 Dota 系列中的一个伪核,拥有很强的生存能力和线上消耗能力.编织者的代表性技能是缩地.缩地带来的隐身.极限移动 ...

  10. 使用python处理selenium中的xpath定位元素的模糊匹配问题

    # 用contains,寻找页面中style属性值包含有sp.gif这个关键字的所有div元素,其中@后面可以跟该元素任意的属性名. self.driver.find_element_by_xpath ...