跨域几种方式
一、什么是跨域
一般一个域名地址的组成:
https://(协议);
www(子域名);
abc.com(主域名);
:8080(端口号);
/img/abc.jpg(请求的资源路径地址);
出于同源策略的限制,js不允许跨域调用非本身域下面的资源。当协议、子域名、主域名、端口号中任意一个不相同时,都算作不同域。不同域之间相互请求资源,就算作“跨域”。
有一点必须要注意:跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。之所以会跨域,是因为受到了同源策略的限制,同源策略要求源相同才能正常进行通信,即协议、域名、端口号都完全一致。
特别说明两点:
第一:如果是协议和端口造成的跨域问题“前台”是无能为力的。
第二:在跨域问题上,域仅仅是通过“URL的首部”来识别而不会根据域名对应的IP地址是否相同来判断。“URL的首部”可以理解为“协议, 域名和端口必须匹配”。
二、什么是同源策略及其限制
同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。它的存在可以保护用户隐私信息,防止身份伪造等(读取Cookie)。
同源策略限制内容有:
Cookie、LocalStorage、IndexedDB
等存储性内容DOM
节点AJAX
请求不能发送
但是有三个标签是允许跨域加载资源:
<img src=XXX/>
<link href=XXX/>
<script src=XXX/>
三、处理跨域方法
一、JSONP
1.原理
利用 <script>元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON 数据。J
SONP请求一定需要对方的服务器做支持才可以。
2.JSONP和AJAX对比
JSONP和AJAX相同,都是客户端向服务器端发送请求,从服务器端获取数据的方式。
但AJAX属于同源策略,JSONP属于非同源策略(跨域请求)。
3.JSONP优缺点
JSONP优点是兼容性好,可用于解决主流浏览器的跨域数据访问的问题。
缺点是仅支持get方法具有局限性。
4.JSONP的流程(以第三方API地址为例,不必考虑后台程序)
1、声明一个回调函数,其函数名(如fn)当做参数值,要传递给跨域请求数据的服务器,函数形参为要获取目标数据(服务器返回的data)。
2、创建一个 <script>标签,把那个跨域的API数据接口地址,赋值给script的src,还要在这个地址中向服务器传递该函数名(可以通过问号传参 :?callback=fn)。
3、服务器接收到请求后,需要进行特殊的处理:把传递进来的函数名和它需要给你的数据拼接成一个字符串,例如:传递进去的函数名是fn,它准备好的数据是 fn([{"name":"jianshu"}])。
4、最后服务器把准备的数据通过HTTP协议返回给客户端,客户端再调用执行之前声明的回调函数(fn),对返回的数据进行操作。
<script type="text/javascript">
function fn(data){
alert(data.msg);
}
</script>
<script type="text/javascript" src="http://crossdomain.com/jsonServerResponse?jsonp=fn"></script>
其中 fn 是客户端注册的回调的函数,目的获取跨域服务器上的json数据后,对数据进行在处理。最后服务器返回给客户端数据的格式为:
fn({msg:'this is json data'})
5.jQuery的jsonp形式
JSONP都是GET和异步请求的,不存在其他的请求方式和同步请求,且jQuery默认就会给JSONP的请求清除缓存。
$.ajax({
url:"http://crossdomain.com/jsonServerResponse",
dataType:"jsonp",
type:"get", //可以省略
jsonpCallback:"fn", //->自定义传递给服务器的函数名,而不是使用jQuery自动生成的,可省略
jsonp:"jsonp", //->把传递函数名的那个形参callback变为jsonp,可省略
success:function(data){
console.log(data);
}
});
二、CORS
1.CORS原理
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
2.CORS优缺点
CORS要求浏览器(>IE10)和服务器的同时支持,是跨域的根本解决方法,由浏览器自动完成。
优点在于功能更加强大支持各种HTTP Method,缺点是兼容性不如JSONP。
只需要在服务器端做一些小小的改造即可:
header("Access-Control-Allow-Origin:*");
header("Access-Control-Allow-Methods:POST,GET");
在响应头上添加 Access-Control-Allow-Origin 属性,指定同源策略的地址。同源策略默认地址是网页的本身。只要浏览器检测到响应头带上了CORS,并且允许的源包括了本网站,那么就不会拦截请求响应。
三、WebSocket
h5添加了新的websocket协议以及对应的api,而且没有同源策略的限制,不存在跨域问题。
通过WebSocket构造函数创建一个WebSocket实例,接收一个请求地址作为参数,此时就已经向服务端发起请求了。
websocket的原理就是服务端作为一个桥的作用,为客户端嫁接起一个可通信的通道,再这个通道开启的状态下可以做到数据相互告知。
具体前端代码如下:
//该构造函数接受一个地址为参数,协议的标识符就是ws。像https一样如果加密的话就是wxs
var socket = new WebSocket('ws://' + 'xxx.xxx.com');
//主动发起通信
//onopen打开链接
ws.onopen = function() {
console.log("打开连接");
//send主动给服务端发送消息
ws.send("客户端:hello,服务端");
};
//接受消息onmessage
ws.onmessage = function(e) {
console.log("客户端接受消息:接收到服务端的消息 " + e.data);
setTimeout(() => {
//关闭ws
ws.close();
}, 5000);
};
//关闭通信
ws.onclose = function(params) {
console.log("client:关闭连接");
};
四、postMessage
如果两个网页不同源,就无法拿到对方的DOM。典型的例子是iframe窗口和 window.open 方法打开的窗口,它们与父窗口无法通信。HTML5为了解决这个问题,引入了一个全新的API:跨文档通信 API(Cross-document messaging)。这个API为window对象新增了一个 window.postMessage 方法,允许跨窗口通信,不论这两个窗口是否同源。具体未深究
网友评论