前端进阶课程之跨域问题详解

261 阅读3分钟

目录:

  • 一:为什么会存在跨域问题?
  • 二:有哪些常见的跨域问题
  • 三:有哪些常见的跨域解决方案?

一:为什么会存在跨域问题?

一句话:大家都知道的 “浏览器同源策略” 导致的,防止跨域资源的访问,很显然,这样是更安全的,要不然,大家都可以访问淘宝的接口,支付宝的接口,那不乱套了。

二:有哪些常见的跨域问题?

  1. cookie,localstory,indexdb无法跨域共享
  2. dom无法跨域获取和操作(iframe嵌套不同域名的页面会常出现)
  3. ajax无法跨域请求

三:有哪些常见的跨域解决方案?

首先这里明确一个概念,不同的跨域问题,需要使用不同的解决方案,而不是我们传统印象中的,跨域问题就只有jsonp,cors等等,这些也只是针对ajax请求跨域问题的解决方案,那其他跨域问题呢?

  • 1: cookie,localstory,indexdb跨域共享问题
  • 1: cookie: 如果是一级域名相同,二级域名不同,那么可以采用document.domain去控制。即只要两个二级域名下的document.domain是一致的,那么就可以cookie共享
  • iframe问题:例如在url1的页面内要嵌入url2的页面,这个时候,我们通常做法是采用iframe去嵌套url2的页面,这时,如果是父子传递怎么传递数据呢? 1: window.name. 2: url的#hash值. 3: window.postMessage(html5新增方法)三者都需要去舰艇其变化,然后获取相应的值。 具体请看,参考文档
  • 2: ajax请求跨域问题
  1. jsonp(动态生成javascript标签,传入callback,后端通过参数返回一段可执行的代码)
  2. webSocket(协议本身不存在跨域问题)
  3. cors (后端设置请求头)
  4. 设置代理(常用的nginx)

四:实际代码解决案例

1: jsonp案例

动态创建script标签,并且执行src引入的代码
window.xxx = function (value) {
    console.log(value)
}
var script = document.createElement('script')
script.src = 'http://x.stuq.com:7001/json?callback=xxx'
document.body.appendChild(script)

后端此时返回的通常是如下格式:一个函数调用表达式
/**/ typeof xxx === 'function' && xxx({msg: "hello world"});

2: window.name.window.postMessage,hash案例

以iframe为例子:
例如:当前页面为http://localhost:8000, 然后嵌入一个src为http://localhost:9000的iframe标签,

var iframe = document.createElement('iframe')
iframe.src = 'localhost:9000/public/hash.html'
document.body.appendChild(iframe)

//方法一:在子iframe中将要传给父页面的参数设置hash,在父页面中动态监听hash变化,从而获取值
子iframe:
var data = '要传的数据';
parent.location.href = `http://localhost:8000#msg=data`
父页面:
window.onhashchange = function () {
  console.log(location.hash) //解析hash,然后获取data
}

方法二:同理hash,在子frame中设置window.name, 然后在父组件中使用iframe.contentWindow.name获取相应的值
子iframe:
var data = '要传的数据';
window.name = data;
父页面:
iframe.contentWindow.name 就可以获取子iframe中window.name的值。


方法三:同理hash,在子iframe中触发postMessage事件,并且传入参数,在父页面中监听messasge事件,获取相应的值
子iframe:
var data = '要传的数据';
parent.postMessage(data, '*')
父页面:
window.addEventListener('message', function(e) {
  console.log(JSON.parse(e.data))
}, false);

3: cors案例

即在后端代码中设置请求头:
Access-Control-Allow-Origin: *

参考文档: