资讯专栏INFORMATION COLUMN

javascript中实现跨域的方式总结

VioletJack / 2349人阅读

摘要:中的跨域请求应该也算是一个重点,具体什么叫跨域,在这里我就不展开了,可以查一下浏览器的同源策略和跨域的定义。再看后台文件文件接收回调函数并把要返回的参数以参数注入的方式注入到回调函数中,再返回给客户端。

js中的跨域请求应该也算是一个重点,具体什么叫跨域,在这里我就不展开了,可以查一下浏览器的同源策略和跨域的定义。原来只知道常用的jsonp和document.domain这两种方式,这几天学习了一下其他几种跨域请求的方式,正好一起做个总结。

第一种方式:jsonp请求

jsonp请求应该是大家最为熟悉的一种(至少是我知道的第一种跨域请求方式)。jsonp的原理是利用
文件底部的

文件接收回调函数并把要返回的参数以参数注入的方式注入到回调函数中,再返回给客户端。

这样的话浏览器解析script标签,并执行返回的js文档,此时服务器返回的数据作为参数,传到页面中定义好的 jsonpBack 函数里.(动态执行回调函数),就拿到了我们需要的跨域数据。

这里补充一点就是jquery对jsonp有着很好的支持,jquery中$.getJSON方法将jsonp的调用方式进行了封装,用起来十分方便,使用的方式如下即可:

第二种方式:document.domain

这种方式用在主域名相同子域名不同的跨域访问中,举个例子:http://a.frame.com和http://b.frame.com 他们的主域名都是frame.com 这两个域名中的文件可以用这种方式进行访问,通过在两个域中具体的文件中设置document.domain="frame.com"就可达到跨域访问的目的。

实际应用中常常用在iframe中窗口之间的访问,根据浏览器的同源策略,浏览器中不同域的框架之间是不能进行js的交互操作的,所以一个窗口是不能拿到另一个窗口中的contentWindow对象的属性和方法的(注意是能拿到contentWindow对象的,只是属性和方法都不可用)。为了能拿到数据,只要在两个iframe中分别写入document.domain="主域名",这样设置之后,就能拿到contentWindow对象的属性和方法了。代码就这么简单的一行,我就不写小例子了。

第三种方式:window.name

window的name属性有个特征:在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置。

这是什么意思呢?通俗来讲,就是比如我在a.html这个页面中设置了window.name="a";然后让window重新加载b.html页面,然后在b.html页面中输出window.name会发现window.name=“a”。所以就算a.html和b.html这两个页面不是在同一个域中的,也可以在b页面中拿到a页面设置的window.name的值,跨域的核心思路就是这个原理。

实际应用中也是常常用在两个iframe之间(需要结合iframe的特性来用),先上一张从别人那边借鉴过来的原理图,我再按照自己的理解进行分析:

图中有三个页面,getDomainData.html是获取数据的页面,null.html是一个和getDomainData.html同域的空页面,它的作用是作为一个中转站,进行数据的过渡。data.html是要获取数据的所在页面,这里有着我们要的数据,它和getDomainData.html处于不同域中,所以取数据是跨域访问。具体的过程是这样的:在getDomainData.html中建立一个子页面iframe,把这个iframe的src指向b.com/data.html,这样当这个iframe加载完成后就可以访问到data.html中的window.name的数据,之后再将iframe的src改为a.com/null.html,跳回getDomainData.html的同一个域,这样根据同源策略,getDomainData.html就可以访问到null.html中取得的data.html的数据了。获取数据以后最好销毁这个iframe,释放掉内存,也保证了安全。下面附上代码小例子:

getDomainData.html:

data.html:

最后的iframe销毁:

第四种方式:window.postMessage

window.postMessages是html5中实现跨域访问的一种新方式,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源。
该方式的使用还是十分简单的,给要发送数据的页面中的window对象调用一个postMessage(message,targetOrigin)方法即可,该方法的第一个参数message为要发送的消息,类型只能为字符串;第二个参数targetOrigin用来限定接收消息的那个window对象所在的域,如果不想限定域,直接使用通配符 * 。再让接收数据页面的window对象监听自身的message事件来获取传过来的消息,消息内容储存在该事件对象的data属性中。简单的小例子如下:

test.html(发送页面):


test2.html(接收页面)

测试结果如下

关于这个用法困扰了我好久,困扰1:因为最后弹出的消息是在test.html,而不是在test2.html中,我不确定是因为test.html包含了test2.html,所以浏览器渲染才弹出的alert,还是test2.html接收到消息的反馈。后来查阅了权威的文档,才有了进一步的理解,应该是test2.html收到消息,以iframe在test.html中渲染加载出的。
困扰2:postMessage的调用对象是目标窗口还是发送窗口,是否能以window形式调用?
查阅文档后得出结论:*postMessage的调用对象,是其他窗口的一个引用,即目标窗口,不是要发送的窗口,(这里比较出乎意料) 而且postMessage想要通信必须使得一个窗口以iframe的形式存在于另一个窗口,或者一个窗口是从另一个窗口通过window.open()或者超链接的形式打开的(同样可以用window.opener获取源窗口);换句话说,你要交换数据,必须能获取目标窗口(target window)的引用,不然两个窗口之间毫无联系,想通信也无能为力,所以不能直接以主页面window的形式调用。

具体的权威解释请看这个链接: window.postMessage

第五种方式:CORS

CORS(Corss-Origin-Resource Sharing,跨源资源共享),是一种网络浏览器的技术规范,它为Web服务器定义了一种方式,允许网页从不同的域访问其资源,而这种访问是被同源策略所禁止的。CORS系统定义了一种浏览器和服务器交互的方式来确定是否允许跨域请求。 它是一个妥协,有更大的灵活性,但比起简单地允许所有这些的要求来说更加安全。
CORS背后的基本思想,就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是应该失败。

CORS的使用还是十分简便的,比如一个简单的GET或者POST请求,在发送的时候给它附加一个额外的origin头部,其中包含请求页面的源信息(协议、域名和端口),以便服务器根据这个头部信息来决定是否给以响应。下面是javascript高级程序设计书上的一个小例子:

Origin:http://www.nczonline.net

如果服务器认为这个请求可以接受,就在Access-Control-Allow-Origin头部中回发相同的源消息(如果是公共资源,可以回发“ * ”)。例如:

Access-Control-Allow-Origin:http://www.nczonline.net

这样设置之后,服务器与浏览器就可以进行跨域信息的交换了。具体的在不同浏览器上的支持和使用,我就不展开了,js高级程序设计书上提到了很多,网上查一下也有很多。

第六种方式:Web Sockets

Web Sockets是一种新浏览器API,能在一个多带带的持久连接上提供全双工、双向通信,使用ws(代替http://)或wss(代替https://)协议,可用于任意的客户端和服务器程序。
web sockets原理:在JS创建了web socket之后,会有一个HTTP请求发送到浏览器以发起连接。取得服务器响应后,建立的连接会使用HTTP升级从HTTP协议交换为web sockt协议。
使用的小例子:

// 创建一个Socket实例
var socket = new WebSocket("ws://www.example.com/server.php"); 

// 打开Socket 
socket.onopen = function(event) { 

  // 发送消息
  socket.send("a secret"); 

  // 监听消息的接收
  socket.onmessage = function(event) { 
    var data=event.data;
    //处理data...
  }; 

  // 监听socket的关闭
  socket.onclose = function(event) { 
    console.log("socket has closed",event); 
  }; 

  // 关闭Socket
  //socket.close() 
};

同样附上权威文档供参考:Web Workers API

总结

除此之外还有一些跨域访问的方式:比如Comet、图像Ping、SSE等,感兴趣的可以直接查找这些内容。在这些跨域访问方式上,各有各的适用访问和相应的限制,需要结合实际来适用。我在这里有个疑问:我自己运用的比较多的就是jsonp这种方式,那么在实际开发中,比较推崇的跨域访问方式是哪种呢?还有就是html5的postMessage是不是可以取代window.name(同样都需要一个iframe作为中间媒介)这类访问方式,这个新API方式是不是在实际中很有效呢?希望有经验的大牛可以解答,不胜感激。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/81807.html

相关文章

  • 在electron中实跨域请求,无需更改服务器端设置

    摘要:很简单,在的模块中配置这样一个参数是什么意思呢顾名思义,他是设置安全性,如果参数设置为,它将禁用相同地方的规则通常测试服并且如果有个非用户设置的参数,就设置和的值为。表示是否允许一个使用的界面来渲染由提交的,,。 很简单,在Electron的BrowserWindow模块中配置这样一个参数: mainWindow = new BrowserWindow({ webPrefere...

    lingdududu 评论0 收藏0
  • 总结域的几种方式

    摘要:比如域的页面通过嵌入了一个域的页面,可以通过以下方法实现和的通信通过跨域以上几种都是双向通信的,即两个,页面与或是页面与页面之间的,下面说几种单项跨域的一般用来获取数据,因为通过标签引入的是不受同源策略的限制的。 跨域整理@(前端笔记) 跨域 只要协议、域名、端口有任何一个不同,都被当作是不同的域。由于浏览器的同源策略,其限制之一是不能通过ajax的方法情趣请求不同源的文档。第二个限制...

    diabloneo 评论0 收藏0
  • 前端跨域总结

    摘要:通过跨域通过引入的不受同源策略的限制,所以我们可以通过标签引入一个或者是一个其他后缀形式如,等的文件,此文件返回一个函数的调用。 1.跨域的定义 只要协议、域名、端口有任何一个不同,就会被当做为不同的域,如果从A域名访问B域名上的资源就叫做跨域。 下面我们来看下几种跨域的方法: 2.document.domain 浏览器的同源策略有一些限制,第一,不能通过ajax方法去请求不同源的资源...

    Yang_River 评论0 收藏0
  • 前端跨域总结

    摘要:通过跨域通过引入的不受同源策略的限制,所以我们可以通过标签引入一个或者是一个其他后缀形式如,等的文件,此文件返回一个函数的调用。 1.跨域的定义 只要协议、域名、端口有任何一个不同,就会被当做为不同的域,如果从A域名访问B域名上的资源就叫做跨域。 下面我们来看下几种跨域的方法: 2.document.domain 浏览器的同源策略有一些限制,第一,不能通过ajax方法去请求不同源的资源...

    honmaple 评论0 收藏0

发表评论

0条评论

VioletJack

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<