一、什么是跨域?
跨域是指从一个域名的网页去请求另一个域名的资源。跨域的严格一点的定义是:只要 协议,域名,端口有任何一个的不同,就被当作是跨域。
域名,协议,端口均相同的为同源。
二、为什么会造成跨域
原因就是安全问题:如果一个网页可以随意地访问另外一个网站的资源,那么就有可能在客户完全不知情的情况下出现安全问题。
三、既然有安全问题,为什么还要跨域
跨域是不可避免的,例如有时公司内部有多个不同的子域,比如一个是location.company.com ,而应用是放在app.company.com , 这时想从 app.company.com去访问 location.company.com 的资源就属于跨域。
四、js跨域
js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中的数据。只要协议、域名、端口有任何一个不同,都被当作是跨域。
五、怎么解决跨域问题
1、通过jsonp跨域
JSONP的原理:通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中指定的函数,并且会把我们需要的json数据作为参数传入。所以jsonp是需要服务器端的页面进行相应的配合的。
在js中,我们直接用XMLHttpRequest
请求不同域上的数据时,是不可以的。但是,在页面上引入不同域上的js脚本文件却是可以的,jsonp正是利用这个特性来实现的。
JSONP的缺点则是:它只支持GET请求而不支持POST等其它类型的HTTP请求。
<script type="text/javascript">
function dosomething(jsondata){
//处理获得的json数据
}
</script>
<script src="http://example.com/data.php?callback=dosomething"></script>
2、CORS
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
它允许浏览器向跨源服务器,发出请求XMLHttpRequest
,从而克服了AJAX只能同源使用的限制。
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
与jsonp相比
1、 JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求。
2、 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理。
3、 JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS)。
参考阮一峰的跨域资源共享 CORS 详解http://www.ruanyifeng.com/blog/2016/04/cors.html
3、服务器端修改字段
服务器端设置 Access-Control-Allow-Origin:* 或者 Access-Control-Allow-Origin:http://www.baidu.com
4、html5方式 -- window.postMessage
这种方式是一种比较新的方式,利用postMessage API实现跨域请求。主要的思想是在请求方(http://getdata.a.com)添加iframe标签,将iframe标签的src属性指定为需要跨域请求的url地址。然后对需要处理的消息进行注册,注册方法里对传递源进行判断,看看是不是需要的url地址,并对参数进行处理。
在父页面添加代码:重点是addeventlisenter和receiveMessage方法
<div class="content">
<script>
//对传进来需要处理的消息进行注册
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event)
{
// For Chrome, the origin property is in the event.originalEvent object.
var origin = event.origin || event.originalEvent.origin;
if (origin !== "http://setdata.a.com")
return;
//传递的消息
console.log(event);
}
</script>
<iframe src="a" frameborder="0" name="myframe" id="corelframe" class="corelframe">
</iframe>
</div>
5、document.domain
这种方式只适合主域名相同,但子域名不同的iframe跨域。
window.name属性就是其中之一,不同域的框架把想要共享的信息放在window.name里面,且此方法只适用于两个iframe之间的跨域。
在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置。