项目中常遇到的几种跨域方案

Posted onesea

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了项目中常遇到的几种跨域方案相关的知识,希望对你有一定的参考价值。

1.jsonp

  jsonp属于最老的一种跨域方案了,我在现在的项目中已经很少见到

技术图片
$(‘#btn‘).click(function(){
    var frame = document.createElement(‘script‘);            
        frame.src = ‘http://localhost:3000/article-list?name=leo&age=30&callback=func‘;
    $(‘body‘).append(frame);
})

function func(res){ 
  console.log(res); 
}
技术图片

可以看到,让我们点击按钮的时候,创建了一个script标签(即会发送一个get请求到src指向的地址),src地址是"localhost:3000/article-list",这个src地址,就是我们请求的服务端接口。注意,这里我们有个参数callback,callback参数就是核心所在。

为什么要定义callback呢?首先我们知道,这个get请求已经被发出去了,那么我们如何接口请求回来的数据呢,callback=func则可以帮我们做这件事。callback参数定义的方法是需要前后端定义好,整个过程就类似于前端声明好一个函数,后端返回执行函数。

 

2.cors

  服务器端对于CORS的支持,主要就是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问。

CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。

浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。 因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

技术图片
一旦服务器通过了"预检"请求,以后每次浏览器正常的CORS请求,就都跟简单请求一样,会有一个Origin头信息字段。服务器的回应,也都会有一个Access-Control-Allow-Origin头信息字段。
下面是"预检"请求之后,浏览器的正常CORS请求。

PUT /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
X-Custom-Header: value
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
上面头信息的Origin字段是浏览器自动添加的。
下面是服务器正常的回应。

Access-Control-Allow-Origin: http://api.bob.com
Content-Type: text/html; charset=utf-8
上面头信息中,Access-Control-Allow-Origin字段是每次回应都必定包含的。
技术图片


CORS与JSONP的使用目的相同,但是比JSONP更强大。
JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。

 

3.postMessage

  window对象新增了一个window.postMessage方法,允许跨窗口通信,不论这两个窗口是否同源。目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。

常用来解决下面三种情况出现的跨域问题:

a.页面和其打开的新窗口的数据传递

b.多窗口之间消息传递

c.页面与嵌套的iframe消息传递

语法:

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

otherWindow其他窗口的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames

message将要发送到其他 window的数据。它将会被结构化克隆算法序列化。这意味着你可以不受什么限制的将数据对象安全的传送给目标窗口而无需自己序列化。

targetOrigin通过窗口的origin属性来指定哪些窗口能接收到消息事件,其值可以是字符串"*"(表示无限制)或者一个URI。在发送消息的时候,如果目标窗口的协议、主机地址或端口这三者的任意一项不匹配targetOrigin提供的值,那么消息就不会被发送;只有三者完全匹配,消息才会被发送。这个机制用来控制消息可以发送到哪些窗口

transfer 可选参数,是一串和message 同时传递的 Transferable 对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。

例1:

技术图片
//  http://test.com/index.html中

<div>
    <iframe id="child" src="http://lsLib.com/lsLib.html"></iframe>
</div>

//通过postMessage()方法向跨域的iframe页面http://lsLib.com/lsLib.html传递消息

window.onload=function(){
    window.frames[0].postMessage(‘getcolor‘,‘http://lslib.com‘);
}

//  http://lslib.com/lslib.html中
//接收消息,并把当前颜色发送给主页面呢 window.addEventListener(‘message‘,function(e){
   console.log(e.data); if(e.source!=window.parent) return; var color=container.style.backgroundColor; window.parent.postMessage(color,‘*‘); },false);
技术图片

例2(txb商家端):

技术图片
//发送(preview.html)
var docWindow = document.getElementById(‘h5-container‘).contentWindow; if (!!docWindow) { docWindow.postMessage({ type: ‘flip‘, pageIndex: pageIndex }, ‘*‘); } //接受(h5-formwork.js) window.addEventListener("message", function receiveMessage(evt) { var data = evt.data; !!data ? typeof evt.data === ‘string‘ ? JSON.parse(data) : data : {}; if (data.type === ‘flip‘) { return Utils.emit(‘flip‘, data.pageIndex); } return Utils.emit(data.type, data); }, false);
技术图片

4.document.domain

5.window.name

6.location.hash

7.http-proxy

8.nginx

9.websocket

后面的几种跨域可参考:https://blog.csdn.net/qq_17175013/article/details/89115804

以上是关于项目中常遇到的几种跨域方案的主要内容,如果未能解决你的问题,请参考以下文章

web跨域解决方案1

跨域以及解决跨域的几种方式

项目中经常遇到的跨域请求的几种方法

vue的跨域方式

跨域的几种方法

Spring跨域的解决方式