为什么要跨域?

跨域问题是浏览器同源策略限制,当前域名的js只能读取同域下的窗口属性。 
一个网站的网址组成包括协议名,子域名,主域名,端口号。比如https://www.github.com/80

其中https是协议名,www.github.com是子域名,github.com是主域名,端口号是80,当在在页面中从一个url请求数据时,如果这个url的协议名、子域名、主域名、端口号任意一个有一个不同,就会产生跨域问题。

即使是在 http://localhost:80/ 页面请求 http://127.0.0.1:80/ 也会有跨域问题(因为域名不一样嘛~)

PS:下浏览器中的 file://域拥有的权限很高,WebKit可以读取磁盘上的文件,IE可以执行CMD,这里大家可以尽情发挥想象,能做的事情太多了!

跨域解决方法小结

  1. 最简单也最常见:使用jsonp ,即json with padding(内填充),顾名思义,就是把JSON填充到一个盒子里
  2. 一劳永逸:直接在服务器端设置跨域资源访问 CORS(Cross-Origin Resource Sharing),设置Request Header头中Access-Control-Allow-Origin为指定可获取数据的域名
  3. 简单有效:直接请求一张图片
  4. 找”爸爸”:通过修改document.domain来跨子域
  5. 哥俩好:通过window.name来跨域接收数据
  6. 新石器时代:使用HTML5的window.postMessage方法跨域

jsonp

核心思想:浏览器的script、img、iframe标签是不受同源策略限制的 ,所以通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中指定的callback函数,并把把我们需要的json数据作为参数传入。在服务器端,当req.params参数中带有callback属性时,则把数据作为callback的参数执行,并拼接成一个字符串后返回。 
- 优点:兼容性好,在很古老的浏览器中也可以用,简单易用,支持浏览器与服务器双向通信。 
- 缺点:只支持GET请求,且只支持跨域HTTP请求这种情况(不支持HTTPS

网页端的代码如下 
jsonp 
创建一个函数tryJSONPadding,并在script标签的源地址中加入这个函数名,服务器端(Node.js写的后端)的处理如下 
服务器端的处理

CORS

核心思想:在服务器端通过检查请求头部的origin,从而决定请求应该成功还是失败。具体的方法是在服务端设置Response Header响应头中的Access-Control-Allow-Origin为对应的域名,实现了CORS(跨域资源共享),这里出于在安全性方面的考虑就是尽量不要用 *,但对于一些不重要的数据则随意,例如图片。下图是某公司阿里云服务器上的CORS设置 
CROS

Node.js实现CORS的方法也很简单,如图。 
NodeJS

图片ping

因为在浏览器中,JS脚本和图片是可以跨域的,所以我们可以直接新建一个图片对象,然后在地址中存放一些简单,这种方法只支持get秦秋,且只能单向地向服务器发送请求,在统计广告曝光次数中比较常见。 
图片ping

寻找相同主域document.domain

对于以下的这两个域名,可以看到他们的主域名都是 example.com,相同于有一个共同的爸爸,且此方法只适用于两个iframe之间的跨域

http://www.example.com/a.html 和http://bbs.example.com/b.html)

 
 
  • 1
  • 2

下面是另外一篇文章中的例子。 
框架一
框架二

window.name

window对象中其实包含了黑魔法的,window.name属性就是其中之一,不同域的框架把想要共享的信息放在window.name里面且此方法只适用于两个iframe之间的跨域

a.com/getDomainData.htmla.com/getDomainData.htmlb.com/data.htmlb.com/data.htmla.com/null.htmla.com/null.html获得数据将iframe的src改为a.com/null.html,跳回原来的域执行回调函数,并销毁iframe,关闭null.html

  1. 在a.com网站添加一个空HTML页。名称为:http://a.com/null.html (用于实现二次跳转) 
    这里写图片描述
  2. 在a.com网站需要获取数据页面(如:http://a.com/getDomainData.html)获取数据]![获取数据
  3. 在b.com中添加获取数据页面 如:http://b.com/data.html 内容需包含:这里写图片描述 
    接下来访问 http://a.com/getDomainData.html 就可返回 http://b.com/data.html 中的window.name中的数据了。

HTML5 中的window.postMessage方法

window.postMessage(message,targetOrigin) 方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。这种方法不能和服务端交换数据,只能在两个窗口(iframe)之间交换数据 
www.example.com中主动发起连接 
发起连接
处于安全考虑,另一个域下的脚本中需要验证消息orgin来源后为http://www.example.com后再发送消息 
验证后发送消息 
event对象,这里的origin为http://localhost:81,仅作为演示 
origin示意图

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐