跨域问题

一,同源

1>基本内容,目的

同源策略是两个页面协议,域名,端口号相同,同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。

2>非同源,共有三种行为受到限制

(1)cookie、LocalStorage 和 IndexDB 无法读取。

只有两个网址域名和端口相同就可以共享cookie,也就是说http://example.com设置的Cookie,可以被https://example.com读取。

(2)DOM 无法获得。(如果两个网页不同源,就无法拿到对方的DOM。典型的例子是iframe窗口和window.open方法打开的窗口,它们与父窗口无法通信。)

(3)AJAX 请求不能发送。

3>解决方法

1)document.domain:这种方法只适用cookie和iframe 窗口.

由于安全限制domain不是可以设置任何值的,我们只能把domain设置成自身或者更高一级的父域,且主域必须相同

两个网页一级域名相同,只是二级域名不同,浏览器允许通过设置document.domain共享 cookie。

如果两个窗口一级域名相同,只是二级域名不同,设置document.domain属性,就可以规避同源政策,拿到DOM。

场景一:http://www.example.com/a.html中有一个iframe,它的src是http://www.example.com/b.html

显示时不同域不能用js获取iframe中的东西

//http://www.example.com/a.html
<iframe src="http://example.com/b.html" id="iframe"></iframe>

document.domain="example.com";
function text(){
	alert(document.getElementById("iframe").contentWindow)
}

//http://www.example.com/b.html
document.domain="example.com";

场景二:ajax的方法去与不同子域的页面交互(document.domain+iframe(隐藏))

原理:让这个iframe载入一个与你想要通过ajax获取数据的目标页面处在相同的域的页面,所以这个iframe可以和这个ajax正常去获取数据,然后是通过上面的document.domain方法

3)解决跨域窗口的通信问题

1》location.hash片段识别符URL的#号后面的部分

1.1》原理:hash变化不会导致页面刷新,所以利用hash传值创建定时器,坚持hash变化,执行相应操作

1.2》优点:解决域名完全不相同的并且实现双向通讯

1.3》缺点:安全问题,location.hash会直接暴露url里;由于url大小限制,支持传递的数据量不大;有些浏览器会在hash变化时产生历史记录,因此可能影响用户体验

1.4》场景:假设github.io域下a.html和shaonian.eu域下b.html存在跨域请求

1)a.html页面创建一个隐藏的iframe,src指向b.html,其中src中可以通过hash传值给b.html

2)b.html页面处理完传入的hash后通过修改a.html的hash值达到将数据传给a.html的目的

需要引入c.html与a.html同源的页面,a.html通过iframe将数据通过hash传给b.html,b.html通过iframe将数据通过传给c.html,c.html通过设置parent.parent.location.hash设置a.html的hash达到目的

3)a.html添加一个定时器,每隔一段时间判断自身的location.hash是否改变,以此响应处理

//bao.com/c.html
var timer=setInterval(checkHash,1000);
function checkHash(){
	parent.parent.location.hash=self.location.hash.substring(1);
}
//bao.com/a.html
<iframe src="http://www.hui.com/b.html" id="iframe"></iframe>
<input type="button" onClick="changeColor()" id="btn"/>

var iframe=document.getElementById("iframe");
var timer=setInterval(checkHash,1000);
function checkHash(){
	switch(location.hash){
		case:"#mainred":
		document.getElementById("btn");
		break;
	}
}
function changeColor(){
	iframe.src="http://www.hui.com/b.html#red"
}
//hui.com/b.html
<iframe src="http://www.bao.com/c.html" id="iframe" style="none"></iframe>

var timer=setInterval(checkHash,1000);
function checkHash(){
	switch(location.hash){
		case:"#red":
		callback();
		break;
	}
}
function callback(){
	document.getElementById("iframe").style.color="red"
}

2》window.name它的name属性有个特征在一个窗口的生命周期内,窗口载入的所有页面都共享一个window.name,每个窗口对window.name都有读写的权限,window.name是持久存在在一个窗口载入过的所有页面中,并不会因为新页面的载入而进行重置。并且可以支持非常长的name值(2MB)

场景:www.examole.com/a.html页面通过js获取不同域www.cnvlogs.com/data.html里的数据

在data.html中给当前的window.name设置a.html需要的数据,在a.html中使用隐藏的iframe充当中间人的角色,有iframe获取data.html的数据然后a.html再去得到iframe获取到的数据

//a.html
<iframe src="http://www.cnblogs.com/data.html" style="display:none"></iframe>
<script>
var iframe=document.getElementById("iframe");
iframe.onload=function(){
	var data=iframe.contentWindow.name;
}
</script>
//www.cnblogs.com/data.html
window.name="我是a.html想要的数据";

3》PostMessage API跨域交换数据

解决LocalStorage 和 IndexDB,HTML5允许跨窗口通信,不论这两个窗口是否同源

不能和服务器交换数据,只能在两个窗口之间交换数据

otherWindow.postMessage(message,targetOrigin,[transfer]);

4)AJAX有三种方法规避这个限制

1》JSONP

最大特点:就是简单适用老式浏览器支持,服务器改造非常小

基本思想是,网页通过添加一个<script>元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。

缺点:只能使用git请求

var jsonpCallback=function(data){
	alert("查询结果:firstName"+data.firstName);
}
var url="http://127.0.0.1:3000/?callback=jsonpCallback";
var script=document.createElement('script');
script.setAttribute('scr',url);
document.getElementsByTagName('head')[0].appendChild(script);

2》WebSocket

WebSocket是一种基于TCP的新的网络协议,使用ws://(非加密)和wss://(加密)作为协议前缀。该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。有一个字段是Origin,表示该请求的请求源(origin),正是因为有了Origin这个字段,所以WebSocket才没有实行同源政策。浏览器发出的WebSocket请求的头信息Sec-WebSocket-Key,Sec-WebSocket-Protocol等。

3》CORS

CORS是跨源资源共享(Cross-Origin Resource Sharing)的缩写。它是W3C标准,是跨源AJAX请求的根本解决方法。CORS允许任何类型的请求。

4>jsonp和cors区别

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

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

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

二.跨域资源共享(CORS)

1>原理

它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制,需要服务器和浏览器共同支持,但是目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。所以实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

2>为什么要验证

基于CSRF(跨站请求伪造)的风险,各主流浏览器会对动态的跨域请求进行特殊的验证处理,验证处理分为简单请求验证处理和预先请求验证处理。

2>触发简单请求与预先请求的条件

只要同时满足以下两大条件就属于简单请求,凡是不同时满足两个条件,就属于预先请求。

1)请求方法是以下三种方法之一:GET,POST,HEAD

2)HTTP的头信息不超出以下几种字段:Accept,Accept-Language,Content-Language,Last-Event-ID,

Content-Type(只限于三个值application/x-www-form-urlencoded    multipart/form-data、text/plain)

3>简单请求

浏览器直接发出CORS请求,它会在头信息之中,增加一个Origin字段(表示请求来自哪个源),表明这是一个跨域请求。

服务器接收到请求后,根据自己的跨域规则,决定是否同意这次请求。

如果Origin指定的域名许可范围内,服务器返回的响应会在头信息里多几个字段,来返回验证结果,如果验证成功会直接返回访问的资源内容。

如果Origin指定的源不在许可范围内,服务器会返回一个正常的HTTP回应,但是回应的头信息没有包含Access-Control-Allow-Origin字段,浏览器就知道出错了,从而抛出一个错误,被XMLHttpRequest的onerror回调函数捕获。(返回403状态码:服务器理解客户端的请求,但是拒绝执行此任务)

Access-Control-Allow-Origin该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。

Access-Control-Allow-Credentials该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。

Access-Control-Expose-Headers:该字段可选。CORS请求时想非基本字段,就必须在Access-Control-Expose-Headers里面指定

4>预先请求

是在正式通信之前,增加一次HTTP查询请求,就是"预检"请求

"预检"请求用的请求方法是OPTIONS是用来询问的要被跨域访问的服务器,是否允许当前域名下的页面发送跨域请求

浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。(403错误)

头信息里面关键字段是Origin(表示请求来自哪个源)。服务器收到"预检"请求以后,检查了Origin、Access-Control-Request-Method该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法)和Access-Control-Request-Headers(该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段)字段以后,确认允许跨源请求,就可以做出回应。

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值