一文搞懂浏览器的跨域问题

跨域资源共享:

通过XHR实现Ajax通信的一个主要限制,来自于跨域安全策略;
浏览器有一个重要的安全策略就是同源政策,他是为了保证用户信息的安全,防止恶意的网站窃取数据。
同源指的是: 域名,协议,和端口三者都相同;
同源策略限制了三种行为:
(1) Cookie、LocalStorage 和 IndexDB 无法读取。
(2) DOM 无法获得。
(3) AJAX 请求不能发送。

这些限制保证了安全,但也带来了许多的不便,所以如何实现跨域资源的共享就成了一个很重要的问题;

现在跨域的手段很多;本文主要介绍CORS方法,JSONP方法,图像Ping;

CORS(crossing-origin resource sharing)跨域资源共享,定义了在必须访问跨域资源时,浏览器与服务器应该如何沟通,cors的做法是,
使用自定义的http头部信息让浏览器与服务器进行沟通,从而决定是否请求或相应是否应该成功;
比如在发送请求的时候,额外的定义一个Origin头部,其中包含请求页面的源信(域名,端口,协议)以便服务器决定是给予响应.
一个示例:
在请求头中含有:Origin : http://www.nczonline.net
如果服务器认为这个请求可以接受,就在Access-COntrol-Allow-Origin发回相同的信息,如果是公共资源则回发"*";
Access-COntrol-Allow-Origin : http://www.nczonline.net
如果没有这个头部,或者源信息不匹配,则浏览器就会驳回这个请求,正常情况下,则会处理这个请求,(注意这里不包含cookie信息)


其他浏览器以及IE10直接通过XHR对象实现了对CORS的原生支持,所以实现CORS通信的关键是服务器,只要服务器实现了CORS接口,就可以跨源通信。
跨域的XHR对象只需传入绝对的URL即可,还可以访问status和statusText属性,同时也支持同步请求;
但也有一些限制:
1.不能使用setRequestHeader()设置自定义的头部;
2.不能发送和接收cookie
3.调用getAllReaponseHeaders()总会返回空字符串;
(因为同源和跨源请求调用了一个对象,所以为了消除歧义,保持代码的可读性,建议同源是使用相对路径,而在跨源时使用绝对路径);


在XHR中实现的CORS跨域请求,可以分为两种,一种是简单请求,一种是复杂请求;
只要同时满足以下两大条件,就属于简单请求。
(1) 请求方法是以下三种方法之一:
HEAD
GET
POST
(2)HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain


凡是不同时满足上面两个条件,就属于非简单请求。
简单请求的流程如上所说,不再赘述;
默认情况下,跨源请求不提供凭据(cookie,http认证及客户端SSl证明等),但是XHR有一个属性,withCredentials可以实现带凭据的请求;
将withCredentials设置为true,可以指定某个请求应该发送凭据;如果服务器接收带凭据的请求,则会用:
Access-Control-Allow-Credentials : true;来响应浏览器;
另外:服务器也可以在preflight响应(接下来会讲到什么事preflight响应)中发送这个头部,表示允许源发送带凭据的请求;


如果是非简单请求,则会使用到preflighted requests(一般称为 预检请求);
CORS通过preflighted requests的透明服务器验证机制支持开发人员使用自定义的头部,get和post之外的方法,以及不同类型的主体内容;
流程如下:(会比简单请求多一次HTTP请求)
浏览器首先发送一个preflight请求,这种请求使用option方法,发送下列头部:
Origin:与简单请求相同;
Access-Control-Request-Method:请求自身的方法;
Access-Control-Request-Header:(可选)自定义的头部信息;


然后服务器收到之后,可以决定是否允许这种类型的请求,服务器在响应中通过以下头部信息与浏览器进行沟通:
Access-Control-Allow-Origin:与简单请求相同;
Access-Control-Allow-Method:允许的方法;
Access-Control-Allow-Header:允许的头部;
Access-Control-Max-Age:应该将这个Preflght请求缓存多长时间(以秒计算)(preflght请求都会按照这个头部说明的时间储存下来)


图像Ping
我们知道一个网页可以从任何页面加载图像,不用担心跨域与否;(因为同源政策限制了一部分的操作,而不是任何跨域操作都不行!)
所以就可以通过动态的创建图像,这时就会使用到图片Ping的技术;
图像Ping是与服务器进行简单,单向的跨域通信的一种方式,请求的数据是通过查询字符串形式发送的,而响应可以是任何内容.
通过侦听onload和onerror两个事件,浏览器能够知道响应是什么时候收到的,但是他不能访问范文报文的任何东西;
示例:
var img = new Image();
img.onerror() = img.onload()  = function(){
//处理函数;
}
img.src = "http://www.example.com/test?name=Nicholas";//请求从这里开始,此例中请求中发送了一个name参数
图像Ping最常使用于跟踪用户点击页面或动态广告曝光次数;
它有两个缺点:一是只能发送get请求,二是只能用于浏览器与服务器的单向通信;


JSONP
填充式JSON,JSON with padding;
JSONP由两部分组成,回调函数和数据;回调函数是当响应到来时应该在页面中调用的函数,数据就是传入回调函数中的JSON数据.
JSON是通过动态

你可能感兴趣的:(前端)