同源策略与跨域资源共享

1.同源策略

同源策略,就是限制JS只能访问与所在页面同一个域(相同协议、域名、端口)的内容。浏览器的整个安全体系均建立在此之上。

支持同源策略的浏览器其实并不会阻止跨域请求的发送和响应的接收,它仅仅是阻止程序不能访问返回的数据而已。

同源策略限制:

1.无法读取非同源网页的cookie,localstorage,IndexDB;

2.无法接触非同源网页的dom;

3.无法获取非同源网页的请求(可以接受,浏览器拒绝响应);

2.跨域资源共享

两种方法:Jsonp和CORS

Jsonp

实际上,Web页面上调用通过<script>标签引用库的时候是不受跨域的影响,凡是拥有"src"这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>。jsonp就是利用这个原理动态加载<script>来实现跨域资源加载。

javascript代码:

function addScriptTag(src) {
  var script = document.createElement('script');
  script.setAttribute("type","text/javascript");
  script.src = src;
  document.body.appendChild(script);
}

window.onload = function () {
  addScriptTag('http://example.com/ip?callback=foo');
}

function foo(data) {
  console.log('Your public IP address is: ' + data.ip);
};

网页加载时添加script便签,并向服务器example.com发送请求,请求的查询字段callback是回调函数的名字,服务器收到请求后,会将数据放在回调函数的参数位置返回。返回的是数据是Json对象。

foo({
  "ip": "8.8.8.8"
});

CORS

CORS(Cross-Origin Resource Sharing)方案是W3C在2014年正式推出的跨域访问方案,是真正的官方解决方案。

这个方案的实需要浏览器和服务器同时支持整个CORS通信过程,都是浏览器自动完成,不需要用户参与。浏览器一旦发现请求跨域,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此CORS通信的关键是服务器。

基本过程:

1.浏览器识别跨域请求,添加请求头信息,增加origin字段请求源

origin:协议+域名+端口

2.如果origin源不在服务器许可范围内,服务器返回一个正常的http回应,浏览器发现回应头信息没有包含Access-Control-Allow-Origin字段,从而抛出错误。

3.如果origin源在服务器许可范围内,返回头信息包含3个与CORS相关的字段:

Access-Control-Allow-Origin:请求源 | *;

Access-Control-Allow-Credentials:是否允许发送Cookie;

Access-Control-Expose-Headers:【字符串】获取头信息。


对于非简单请求如PUT,DELETE方法,或者Content-Type类型为application/json的请求,会在正式请求之前,先做一次预检请求(http查询),先询问服务器,当前origin源是否在服务器许可范围内,使用哪些http动作和头字段信息。

1.浏览器识别跨域请求,添加请求头信息,发出一个“预检”请求;

请求方法OPTIONS;

Origin:http://api.bob.com

Access-Control-Request-Method:PUT

2.服务器收到预检请求后,检查Origin,Access-Control-Request-Method字段,如允许跨域请求,

则服务器返回的http回应字段Access-Control-Allow-Origin包含请求域;如服务器否定了预检请求,

则返回没有任何cors头信息的正常的http回应,浏览器抛出错误。

3.一旦服务器通过了预检请求,浏览器再发送一个简单请求,添加origin头字段信息就ok,服务器回应的头信息里包含

Access-Control-Allow-Origin字段。


总结

JSONP是以动态创建script标签为基础的一种编程技巧,来实现跨域获取JSON数据。老式浏览器支持。

CORS方案实现简单,同时支持多种方式请求,但是不支持IE10以下浏览器。目前市面上所有的手机浏览器是全部支持CORS的,如果是为手机提供跨域服务CORS就够了。

另:h5提供了postMessage跨窗口通信API,允许跨窗口通信。

父窗口代码:var popup = window.open('http://bbb.com', 'title');
// 父窗口向子窗口发消息
popup.postMessage('Hello World!', 'http://bbb.com');
子窗口代码: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.Web Sockets

Web Sockets的目标是在一个单独的持久的连接上提供双全工、双向通信。也就是说,创建了一个Web Sockets之后,浏览器会马上尝试创建连接,连接成功后就可以发送和接收数据。


与http协议不同的是,1)Web Sockets更高级的支持实时更新数据,相比于通过ajax的request与response服务器被动的传递数据,Web Sockets在建立连接之后服务器有数据更新就会发送数据给服务器触发message事件;2)与HTTP的请求与响应携带的数据量相比,Web Sockets更节约流量。当然Web Sockets也是一个协议,是http连接之后服务器升级的协议,所以与服务器端通信时都要先通过HTTP连接。

var socket = new WebSocket("ws://www.example.com/server.php");
socket.send();
//通过message事件接收数据
socket.onmessage = function(event){
     var data = event.data;
};
//连接成功时触发open事件
socket.onopen = function(){
     ....
};
//连接错误时触发error,连接关闭时触发close事件

socket.close();
注意:如果不需要双向通信,只需要读取服务器数据,那ajax和jsonp或者CORS就可以实现。

web sockets非常适合实时数据的更新。


参考文章:http://javascript.ruanyifeng.com/bom/cors.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值