同源策略
同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。
这些限制资源包括:
(1) Cookie、LocalStorage 和 IndexDB无法读取。
(2) DOM无法获得。
(3) AJAX 请求不能发送。
关于一个源的定义
所谓"同源"指的是"三个相同"。只要协议、域名、端口有任何一个不同,都被当作是不同的域。
1. 协议相同
2. 域名相同
3. 端口相同
下表给出了相对http://store.company.com/dir/page.html 同源检测的示例:
![](https://img.haomeiwen.com/i1281633/ec7141e6454a6436.png)
什么是JS跨域,如何解决JS跨域问题?
javascript出于安全考虑,不允许不同源间的网站进行文本或脚本间的资源交互,而采用某些技术使得不同源间的网站也能够进行上述行为的技术就叫做跨域。
跨域方式 | 原理 | 备注 |
---|---|---|
CORS跨域 | 使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败。 | |
jsonp跨域 | 在js中,我们直接用XMLHttpRequest请求不同域上的数据时,是不可以的。但是,在页面上引入不同域上的js脚本文件却是可以的,jsonp正是利用这个特性来实现的。 | 只能实现GET请求,兼容性差 |
修改document.domain来跨子域 | 设置document.domain一致 | document.domain的设置是有限制的,我们只能把document.domain设置成自身或更高一级的父域,且主域必须相同。 |
window.name跨域 | 即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限 | |
使用HTML5的window.postMessage方法跨域 | 可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源。 |
跨域实例
1.CORS跨域:
<script type="text/javascript">
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://segmentfault.com/u/trigkit4/",true);
xhr.send();
</script>
将需要跨域访问的地址写为绝对地址,服务器端对于CORS的支持,主要就是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问。
2.JSONP跨域
<script type="text/javascript">
function dosomething(jsondata){
//处理获得的json数据
}
</script>
<script src="http://example.com/data.php?callback=dosomething"></script>
js文件载入成功后会执行我们在url参数中指定的函数,并且会把我们需要的json数据作为参数传入。所以jsonp是需要服务器端的页面进行相应的配合的。
3.修改document.domain跨域
若http://www.example.com/a.html
想要访问在这个页面里面的一个iframe,它的src是http://example.com/b.html
, 很显然,这个页面与它里面的iframe框架是不同域的,所以我们是无法通过在页面中书写js代码来获取iframe中的东西的。
解决方法:
- 在页面
http://www.example.com/a.html
中设置document.domain:
<iframe id = "iframe" src="http://example.com/b.html" onload = "test()"></iframe>
<script type="text/javascript">
document.domain = 'example.com';//设置成主域
function test(){
alert(document.getElementById('iframe').contentWindow);//contentWindow 可取得子窗口的 window 对象
}
</script>
- 在页面
http://example.com/b.html
中也设置document.domain:
<script type="text/javascript">
document.domain = 'example.com';//在iframe载入这个页面也设置document.domain,使之与主页面的document.domain相同
</script>
4.使用window.name跨域
<!--a.html-->
<script>
window.name = 'hello';
setTimeout(function () {
window.location = 'b.html';
},1000);
</script>
在b.html中使用win.name输出:
<!-- b.html -->
<script>
alert(window.name);
</script>
5.使用window.postMessage实现跨域
<!-- a.html -->
<script>
function onLoad() {
var iframe = document.getElementById('iframe');
var win = iframe.contentWindow;
win.postMessage('hello');
}
</script>
<iframe id = 'iframe' src="http://www.test.com/b.html" onload="onLoad()"></iframe>
<!-- b.html -->
<script>
window.onmessage = function (e) {
e = e || event;
alert(e.data);
}
</script>
网友评论