跨域在前端是个很常见的场景。
首先,我们先来了解下什么是跨域,什么情况下出现跨域。

概念以及场景

跨域的始作俑者是同源策略:

同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。

换句话说就是,浏览器限制了,我们在一个页面下面去调用另外一个源的资源。
最常见的场景是我们在当前页面下调用了另一个源的接口。结果浏览器直接报错了,说不行,不能这样干。

下面是同源的定义:

如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有相同的源。

造成跨域的两种策略

浏览器的同源策略会导致跨域,这里同源策略又分为以下两种

  1. DOM同源策略:禁止对不同源页面DOM进行操作。这里主要场景是iframe跨域的情况,不同域名的iframe是限制互相访问的。
  2. XmlHttpRequest同源策略:禁止使用XHR对象向不同源的服务器地址发起HTTP请求。

跨域解决方案

跨域的问题是有解决方案的。

跨域资源共享

CORS是一个W3C标准,全称是”跨域资源共享”(Cross-origin resource sharing)。 对于这个方式,阮一峰老师总结的文章特别好,希望深入了解的可以看一下http://www.ruanyifeng.com/blog/2016/04/cors.html。

jsnop

利用 “在HTML标签里,一些标签比如script、img这样的获取资源的标签是没有跨域限制的” 来实现跨域

服务器代理

document.domain来跨子域

对于主域名相同,而子域名不同的情况,可以使用document.domain来跨域 这种方式非常适用于iframe跨域的情况。

window.name进行跨域

window.name跨域同样是受到同源策略限制,父框架和子框架的src必须指向统一域名。
window.name的优势在于,name的值在不同的页面(或者不同的域名),加载后仍然存在,除非你显示的更改。并且支持的长度达到2M.

location.hash跨域

location.hash方式跨域,是子框架具有修改父框架src的hash值,通过这个属性进行传递数据,且更改hash值,页面不会刷新。
但是传递的数据的字节数是有限的。

补充: 其实还有一些方法,比如window.name和location.hash。
就很适用于iframe的跨域,不过iframe用的比较少了,所以这些方法也就有点过时了。

使用postMessage实现页面之间通信

window.postMessage是一个HTML5的api,允许两个窗口之间进行跨域发送消息。
这个应该就是以后解决dom跨域通用方法了,具体可以参照MDN。

一些实用方法

  • 跨域下获取iframe的父页面URL:
1
2
3
4
5
6
7
8
9
10
11
12
const getParentHost = function() {
let host = null;
if (parent !== window) {
try {
host = parent.location.origin;
} catch (e) {
const url = document.referrer;
host = url.split('/').splice(0, 3).join('/');
}
}
return host;
}

参考

  1. 跨域的那些事儿
  2. 前端跨域整理
  3. 不要再问我跨域的问题了