跨域

浏览器同源策略

浏览器出于安全考虑,默认情况下,只允许在本域接口下进行数据交互。这是浏览器的一种安全保护机制。主要限制有两个方面:

一、不同源的文档不能通过ajax实现请求,例如通过XHR实现Ajax通信,默认,XHR只能访问与包含它的页面位于同一个域中的资源,而不能访问其他域下的资源。

二、浏览器中不同域的框架也是不能通过js进行交互操作。

什么是跨域?

只要协议、域名、端口号中有任何一个不相同,就算是不同的域。要实现在不同域之间进行数据交互,就需要用到跨域的技术。

对于端口号和协议不同的情况,只能通过后台实现跨域。

跨域的几种方式:

1、CORS(跨域资源共享Cross-Origin Resource Sharing)

定义了在必须跨域访问的情况下,服务器和浏览器是如何进行沟通。cors背后的思想就是通过自定义的HTP头部的信息的反馈,决定整个请求响应过程的成败。

比较一下在使用cors实现跨域和没有跨域的情况下,ajax代码的区别:

var xhr=new XMLHttpRequest();

xhr.open('get','/loadMore?index='+pageIndex+'&length=5',true)  //  没有cors  url是一个相对路径

xhr.send();

var  xhr=new  XMLHttpRequest();

xhr.open('get', 'http://baidu.com:8080/getNews', true); // cors 实现跨域    URL换成其他域的绝对地址

xhr.send();

如上使用get方法发送一个请求时,在他的头部附加一个Origin头部,其中包含请求页面的源信息(协议、域名、端口)

Origin: http://baidu.com:8080

服务器根据这个头部信息来决定是否允许响应,如果服务器认为这个请求可以接受,就会在Access-Control-Allow-Origin的头部中回发同样的源信息

Access-Control-Allow-Origin: http://baidu.com:8080

如果没有这个头部,或者源信息不匹配,浏览器就会驳回请求。

2、JSONP

(JSON with padding)是JSON的一种使用格式,可以让网页访问其他网域下的资源,也叫填充式JSON

JSONP的特性:

html中的script标签可以引用其他域中的文件,可实现跨域访问。需要后端的支持与配合。

JSONP由两部分组成:回调函数和数据;   

回调函数就是在响应到来的时候,在页面中调用的函数,数据就是服务器发过来的json数据

callback({"name":"sty"})

使用jsonp来实现跨域:

js文件

var script=document.createElement('script');  //创建script元素

script.src='http://a.jrg.com:8080/getNews?callback=appendHtml';  //指定要访问的URL,其中回调函数是appendChild,用于处理数据

document.head.appendChild(script);  //在页面头部添加script节点

document.head.removeChild(script);  //在实现跨域功能后,移除script节点,保持页面的简洁

后端:

var cb = req.query.callback;

if(cb) {

     res.send(cb+'('+JSON.stringify(data)+')');

} else {

res.send(data);

}

JSONP的优缺点

JSONP的优点是:它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持;并且在请求完毕后可以通过调用callback的方式回传结果。

JSONP的缺点则是:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。

CORS和JSONP对比

1、 JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求。

2、 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理。

3、 JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS)

使用JSONP实现跨域,也会存在一定的安全隐患,例如XSS攻击

3、降域

浏览器中不同域的框架也是不能通过js进行交互的,但是不同框架之间可以获取到window对象,但却无法获取到相应的属性和方法。

例如  a.baidu.com 域下的一个 html 文档里有一个在其他域下(b.baidu.com)的 iframe 框架,在a.baidu.com 中并不能访问到 b.baidu.com 里的数据;

但可以获取到 b.baidu.com 中的 window 对象,但是这时 window 的属性和方法并不可用,两个文件中使用 document.domain('baidu.com')方法 把域名都降到baidu.com;

这样就可以在 a.baidu.com 中使用 iframe 里面的 window 的所有属性和方法了,通过window.frames[0] 获取到 iframe 框架,但是这时再通过window.frames[0].document.querySelector(element) 获取到 iframe 里的 element 元素。

在b.baidu.com 中通过window.parent.document.querySelector(element) 获取到html里的元素。

document.domain只适用于不同子域的框架之间实现跨域访问。

主要使用document.domain()


4、postMessage

这是HTML5的一种跨域访问资源的方法。

window.postMessage(message,targetOrigin)方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。

document.querySelector('.main input').addEventListener('input',function() {

console.log(this.value);

window.frames[0].postMessage(this.value,"*")  //访问不同源的框架的message

})

window.addEventListener('message',function(e) {  /*在window上绑定一个监听事件,监测message*/

document.querySelector('.main input').value=e.data//通过e.data可以监听到别人发给我的信息

console.log(e.data);

})

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

推荐阅读更多精彩内容

  • 1. 什么是跨域? 跨域一词从字面意思看,就是跨域名嘛,但实际上跨域的范围绝对不止那么狭隘。具体概念如下:只要协议...
    w_zhuan阅读 547评论 0 0
  • 1. 什么是跨域? 跨域一词从字面意思看,就是跨域名嘛,但实际上跨域的范围绝对不止那么狭隘。具体概念如下:只要协议...
    他在发呆阅读 830评论 0 0
  • 跨域资源共享 CORS 对于web开发来讲,由于浏览器的同源策略,我们需要经常使用一些hack的方法去跨域获取资源...
    默默先生Alec阅读 609评论 0 0
  • 什么是跨域? 2.) 资源嵌入:、、、等dom标签,还有样式中background:url()、@font-fac...
    电影里的梦i阅读 2,397评论 0 5
  • 羌管翩逐花影,闹春风。倦人倚门叹镜心乱空。 花期负,朝与暮,盼君顾,自是君来不知奴归处。
    徐小丸子小姐阅读 356评论 6 3