不用再问小编跨域的标题了

2018/07/16 · 基础技巧 ·
跨域

最初的作品出处: 写Bug   

写下那篇文章后作者想,要不然后就把这种基础的常见知识都归到这一个“不要再问小编XX的主题材料”,产生一名目多数内容,希望大家看完之后再有人问您这个难题,你心中会窃喜:“嘿嘿,是时候表现真正的才干了!”
一、无须再问笔者this的针对性难题了

跨域那八个字就疑似一块狗皮膏药一样黏在每贰个前端开荒者身上,无论你在劳作上只怕面试中无可幸免会超出这一个主题素材。为了敷衍面试,作者每一次都不管背多少个方案,也不明了怎么要如此干,反正面完就足以扔了,笔者想工作上也不会用到那么多非常不佳的方案。到了着进行事,开垦条件有webpack-dev-server解决,上线了服务端的大佬们也会配好,配了怎样小编不管,反正不会跨域正是了。日子也就这么混过去了,终于有一天,笔者以为无法再持续这么混下去了,笔者自然要通透到底搞懂那些事物!于是就有了那篇小说。

要调节跨域,首先要理解为何会有跨域那个标题应际而生

诚然,大家这种搬砖工人就是为着混口饭吃嘛,好好的调个接口告诉作者跨域了,这种阻碍我们轻巧搬砖的作业真恶心!为何会跨域?是何人在搞专门的学问?为了找到这么些主题素材的始作俑者,请点击浏览器的同源战略。
如此这般官方的东西真难懂,没涉及,至少你领悟了,因为浏览器的同源计策导致了跨域,就是浏览器在搞专业。
之所以,浏览器为何要搞职业?正是不想给好日子大家过?对于那样的挑剔,浏览器甩锅道:“同源战术限制了从同三个源加载的文书档案或脚本怎么样与来自另二个源的财富举办互相。那是一个用来隔断潜在恶意文件的重大安全机制。”
如此那般官方的话术真难懂,没涉及,至少你理解了,就好像那是个平平安安机制。
因而,终究怎么须要那样的安全机制?那样的安全部制消除了哪些难题?别急,让大家三回九转研商下去。

尚无同源计策限制的两大危险现象

据自身打听,浏览器是从三个地方去做那一个同源战略的,一是指向接口的伸手,二是指向Dom的询问。试想一下并未有那样的限制上述二种动作有怎么着危急。

尚无同源战略限制的接口央浼

有贰个十分的小的事物叫cookie我们应该明白,一般用来拍卖登陆等景况,目标是让服务端知道什么人发出的此番央浼。假使你央求了接口实行登陆,服务端验证通过后会在响应头加入Set-Cookie字段,然后下一次再发需要的时候,浏览器会自动将cookie附加在HTTP诉求的头字段Cookie中,服务端就能够清楚那么些用户已经报到过了。知道那个未来,我们来看现象:
1.您准备去清空你的购物车,于是打开了买买买网址www.maimaimai.com,然后登入成功,一看,购物车东西如此少,不行,还得买多点。
2.你在看有啥东西买的经过中,你的好好朋友发给你三个链接www.nidongde.com,一脸yin笑地跟你说:“你懂的”,你坚决展开了。
3.您饶有兴致地浏览着www.nidongde.com,何人知这些网址暗地里做了些不可描述的事务!由于并未有同源计策的界定,它向www.maimaimai.com发起了伏乞!聪明的你势必想到上边的话“服务端验证通过后会在响应头参加Set-Cookie字段,然后后一次再发央浼的时候,浏览器会自行将cookie附加在HTTP央浼的头字段Cookie中”,那样一来,那几个不法兰西网球国际赛站就也正是登入了你的账号,可以为所欲为了!假诺那不是四个买买买账号,而是你的银行账号,那……
那正是风传中的CSEscortF攻击浅谈CS奥迪Q5F攻击格局。
看了那波CSOdysseyF攻击自个儿在想,尽管有了同源计策限制,但cookie是大廷广众的,还不是同等能砍下来。于是小编看了一些cookie相关的篇章聊一聊
cookie、库克ie/Session的编写制定与安全,知道了服务端能够安装httpOnly,使得前端不能够操作cookie,若无那样的安装,像XSS攻击就足以去取获得cookieWeb安全测验之XSS;设置secure,则保险在https的加密通讯中传输以免截获。

并未有同源战术限制的Dom查询

1.有一天你刚睡醒,收到一封邮件,说是你的银行账号有风险,赶紧点进www.yinghang.com改密码。你吓尿了,赶紧点进去,依旧熟悉的银行登入界面,你坚决输入你的账号密码,登陆进去看看钱有未有少了。
2.睡眼朦胧的您没看清楚,平常探问的银行网址是www.yinhang.com,而未来走访的是www.yinghang.com,这么些钓鱼网址做了如何啊?

// HTML <iframe name=”yinhang”
src=”www.yinhang.com”></iframe> // JS //
由于并未同源战术的限定,钓鱼网址能够一向拿到其余网址的Dom const iframe =
window.frames[‘yinhang’] const node =
iframe.document.getElementById(‘你输入账号密码的Input’)
console.log(`得到了那一个${node},笔者还拿不到您刚刚输入的账号密码吗`)

1
2
3
4
5
6
7
// HTML
<iframe name="yinhang" src="www.yinhang.com"></iframe>
// JS
// 由于没有同源策略的限制,钓鱼网站可以直接拿到别的网站的Dom
const iframe = window.frames[‘yinhang’]
const node = iframe.document.getElementById(‘你输入账号密码的Input’)
console.log(`拿到了这个${node},我还拿不到你刚刚输入的账号密码吗`)

经过大家理解,同源战术确实能避开一些朝不虑夕,不是说有了同源战术就安枕无忧,只是说同源计谋是一种浏览器最中心的平安机制,究竟能抓牢一点抨击的资金。其实远非刺不穿的盾,只是攻击的本金和口诛笔伐成功后获取的裨益成不成正比。

跨域正确的展开药格局

由此对同源战术的问询,大家应有要铲除对浏览器的误解,同源计策是浏览器做的一件善事,是用来防卫来自旁门歪道的口诛笔伐,但总不可能为了不让坏蛋进门而把整个人都拒绝在门外呢。没有错,我们这种正人君子只要打开药格局准确,就活该能够跨域。
上面将贰个个示范正确打开药格局,但在此以前,有个别打算干活要做。为了当地演示跨域,我们必要:
1.随意跑起一份前端代码(以下前端是随意跑起来的vue),地址是:9099。
2.随意跑起一份后端代码(以下后端是随意跑起来的node
koa2),地址是:9971。

同源计谋限制下接口央求的不错展开药格局

1.JSONP
在HTML标签里,一些标签举例script、img那样的收获财富的价签是从未有过跨域限制的,利用那或多或少,大家得以如此干:

后端写个小接口

// 管理成功失利再次来到格式的工具 const {successBody} = require(‘../utli’)
class CrossDomain { static async jsonp (ctx) { // 前端传过来的参数 const
query = ctx.request.query // 设置一个cookies ctx.cookies.set(‘tokenId’,
‘1’) //
query.cb是内外端约定的不二诀窍名字,其实就是后端再次来到三个直接实行的情势给前端,由于前端是用script标签发起的央浼,所以回来了这一个主意后约等于当下实践,並且把要回到的数目放在方法的参数里。
ctx.body = `${query.cb}(${JSON.stringify(successBody({msg: query.msg},
‘success’))})` } } module.exports = CrossDomain

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 处理成功失败返回格式的工具
const {successBody} = require(‘../utli’)
class CrossDomain {
  static async jsonp (ctx) {
    // 前端传过来的参数
    const query = ctx.request.query
    // 设置一个cookies
    ctx.cookies.set(‘tokenId’, ‘1’)
    // query.cb是前后端约定的方法名字,其实就是后端返回一个直接执行的方法给前端,由于前端是用script标签发起的请求,所以返回了这个方法后相当于立马执行,并且把要返回的数据放在方法的参数里。
    ctx.body = `${query.cb}(${JSON.stringify(successBody({msg: query.msg}, ‘success’))})`
  }
}
module.exports = CrossDomain
 

粗略版前端

<!DOCTYPE html> <html> <head> <meta
charset=”utf-8″> </head> <body> <script
type=’text/javascript’> //
后端重临间接实行的主意,也正是推行那些办法,由于后端把重回的数目放在方法的参数里,所以这里能获得res。
window.jsonpCb = function (res) { console.log(res) } </script>
<script
src=”
type=’text/javascript’></script> </body> </html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <script type=’text/javascript’>
      // 后端返回直接执行的方法,相当于执行这个方法,由于后端把返回的数据放在方法的参数里,所以这里能拿到res。
      window.jsonpCb = function (res) {
        console.log(res)
      }
    </script>
    <script src=’http://localhost:9871/api/jsonp?msg=helloJsonp&cb=jsonpCb’ type=’text/javascript’></script>
  </body>
</html>

简言之包装一下前端这么些套路

JavaScript

/** * JSONP央浼工具 *原文出处。 @param url 必要的地方 * @param data
必要的参数 * @returns {Promise<any>} */ const request = ({url,
data}) => { return new Promise((resolve, reject) => { //
管理传参成xx=yy&aa=bb的花样 const handleData = (data) => { const keys
= Object.keys(data) const keysLen = keys.length return keys.reduce((pre,
cur, index) => { const value = data[cur] const flag = index !==
keysLen – 1 ? ‘&’ : ” return `${pre}${cur}=${value}${flag}` }, ”) }
// 动态创设script标签 const script = document.createElement(‘script’) //
接口重回的数目得到 window.jsonpCb = (res) => {
document.body.removeChild(script) delete window.jsonpCb resolve(res) }
script.src = `${url}?${handleData(data)}&cb=jsonpCb`
document.body.appendChild(script) }) } // 使用办法 request({ url:
”, data: { // 传参 msg: ‘helloJsonp’ }
}).then(res => { console.log(res) })

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/**
* JSONP请求工具
* @param url 请求的地址
* @param data 请求的参数
* @returns {Promise<any>}
*/
const request = ({url, data}) => {
  return new Promise((resolve, reject) => {
    // 处理传参成xx=yy&aa=bb的形式
    const handleData = (data) => {
      const keys = Object.keys(data)
      const keysLen = keys.length
      return keys.reduce((pre, cur, index) => {
        const value = data[cur]
        const flag = index !== keysLen – 1 ? ‘&’ : ”
        return `${pre}${cur}=${value}${flag}`
      }, ”)
    }
    // 动态创建script标签
    const script = document.createElement(‘script’)
    // 接口返回的数据获取
    window.jsonpCb = (res) => {
      document.body.removeChild(script)
      delete window.jsonpCb
      resolve(res)
    }
    script.src = `${url}?${handleData(data)}&cb=jsonpCb`
    document.body.appendChild(script)
  })
}
// 使用方式
request({
  url: ‘http://localhost:9871/api/jsonp’,
  data: {
    // 传参
    msg: ‘helloJsonp’
  }
}).then(res => {
  console.log(res)
})

2.空iframe加form
密切的仇敌或许发掘,JSONP只可以发GET诉求,因为本质上script加载财富正是GET,那么一旦要发POST须要如何是好吧?

后端写个小接口

// 管理成功失利重临格式的工具 const {successBody} = require(‘../utli’)
class CrossDomain { static async iframePost (ctx) { let postData =
ctx.request.body console.log(postData) ctx.body = successBody({postData:
postData}, ‘success’) } } module.exports = CrossDomain

1
2
3
4
5
6
7
8
9
10
// 处理成功失败返回格式的工具
const {successBody} = require(‘../utli’)
class CrossDomain {
  static async iframePost (ctx) {
    let postData = ctx.request.body
    console.log(postData)
    ctx.body = successBody({postData: postData}, ‘success’)
  }
}
module.exports = CrossDomain

前端

原文出处。const requestPost = ({url, data}) => { //
首先创立两个用来发送数据的iframe. const iframe =
document.createElement(‘iframe’) iframe.name = ‘iframePost’
iframe.style.display = ‘none’ document.body.appendChild(iframe) const
form = document.createElement(‘form’) const node =
document.createElement(‘input’) //
注册iframe的load事件处理程序,倘若您须求在响应重返时实行一些操作的话.
iframe.addEventListener(‘load’, function () { console.log(‘post
success’) }) form.action = url // 在钦命的iframe中试行form form.target =
iframe.name form.method = ‘post’ for (let name in data) { node.name =
name node.value = data[name].toString()
form.appendChild(node.cloneNode()) } // 表单成分要求增添到主文书档案中.
form.style.display = ‘none’ document.body.appendChild(form)
form.submit() // 表单提交后,就足以去除那些表单,不影响后一次的数目发送.
document.body.removeChild(form) } // 使用格局 requestPost({ url:
”, data: { msg: ‘helloIframePost’ }
})

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
const requestPost = ({url, data}) => {
  // 首先创建一个用来发送数据的iframe.
  const iframe = document.createElement(‘iframe’)
  iframe.name = ‘iframePost’
  iframe.style.display = ‘none’
  document.body.appendChild(iframe)
  const form = document.createElement(‘form’)
  const node = document.createElement(‘input’)
  // 注册iframe的load事件处理程序,如果你需要在响应返回时执行一些操作的话.
  iframe.addEventListener(‘load’, function () {
    console.log(‘post success’)
  })
 
  form.action = url
  // 在指定的iframe中执行form
  form.target = iframe.name
  form.method = ‘post’
  for (let name in data) {
    node.name = name
    node.value = data[name].toString()
    form.appendChild(node.cloneNode())
  }
  // 表单元素需要添加到主文档中.
  form.style.display = ‘none’
  document.body.appendChild(form)
  form.submit()
 
  // 表单提交后,就可以删除这个表单,不影响下次的数据发送.
  document.body.removeChild(form)
}
// 使用方式
requestPost({
  url: ‘http://localhost:9871/api/iframePost’,
  data: {
    msg: ‘helloIframePost’
  }
})

3.CORS

CO库罗德S是贰个W3C标准,全称是”跨域能源分享”(Cross-origin resource
sharing)跨域能源分享 COCR-VS
详解。看名字就通晓这是拍卖跨域难题的科班做法。CO翼虎S有三种诉求,轻易央浼和非轻便央求。

原文出处。此地引用上边链接阮一峰先生的文章证实一下简练央浼和非简单乞请。
浏览器将COENCORES乞请分成两类:轻便诉求(simple
request)和非简单哀告(not-so-simple request)。

若果同有时候满意以下两大条件,就属于简单诉求。
(1) 央求方法是以下两种艺术之一:

  • HEAD
  • GET
  • POST

(2)HTTP的头消息不超越以下两种字段:

  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type:只限于多个值application/x-www-form-urlencoded、multipart/form-data、text/plain

1.简练央求
后端

// 处理成功失败重临格式的工具 const {successBody} = require(‘../utli’)
class CrossDomain { static async cors (ctx) { const query =
ctx.request.query // *时cookie不会在http诉求中带上
ctx.set(‘Access-Control-Allow-Origin’, ‘*’) ctx.cookies.set(‘tokenId’,
‘2’) ctx.body = successBody({msg: query.msg}, ‘success’) } }
module.exports = CrossDomain

1
2
3
4
5
6
7
8
9
10
11
12
13
// 处理成功失败返回格式的工具
const {successBody} = require(‘../utli’)
class CrossDomain {
  static async cors (ctx) {
    const query = ctx.request.query
    // *时cookie不会在http请求中带上
    ctx.set(‘Access-Control-Allow-Origin’, ‘*’)
    ctx.cookies.set(‘tokenId’, ‘2’)
    ctx.body = successBody({msg: query.msg}, ‘success’)
  }
}
module.exports = CrossDomain
 

前面三个什么也不用干,正是例行发乞请就可以,要是必要带cookie的话,前后端都要设置一下,上面那多少个非轻易乞请例子会看到。

fetch(` => {
console.log(res) })

1
2
3
fetch(`http://localhost:9871/api/cors?msg=helloCors`).then(res => {
  console.log(res)
})

原文出处。2.非简便央浼
非轻巧供给会发出一回预检查评定乞请,重临码是204,预检验通过才会真的发出央求,这才重返200。这里经过前端发乞求的时候增添多个异常的headers来触发非轻巧诉求。
图片 1

后端

// 管理成功战败再次回到格式的工具 const {successBody} = require(‘../utli’)
class CrossDomain { static async cors (ctx) { const query =
ctx.request.query //
假如必要http乞求中带上cookie,供给前后端都设置credentials,且后端设置钦定的origin
ctx.set(‘Access-Control-Allow-Origin’, ”)
ctx.set(‘Access-Control-Allow-Credentials’, true) //
非简要需要的CO奥迪Q7S央求,会在标准通讯在此以前,增添叁遍HTTP查询要求,称为”预检”伏乞(preflight)
//
这种情状下除了安装origin,还索要设置Access-Control-Request-Method以及Access-Control-Request-Headers
ctx.set(‘Access-Control-Request-Method’, ‘PUT,POST,GET,DELETE,OPTIONS’)
ctx.set(‘Access-Control-Allow-Headers’, ‘Origin, X-Requested-With,
Content-Type, Accept, t’) ctx.cookies.set(‘tokenId’, ‘2’) ctx.body =
successBody({msg: query.msg}, ‘success’) } } module.exports =
CrossDomain

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 处理成功失败返回格式的工具
const {successBody} = require(‘../utli’)
class CrossDomain {
  static async cors (ctx) {
    const query = ctx.request.query
    // 如果需要http请求中带上cookie,需要前后端都设置credentials,且后端设置指定的origin
    ctx.set(‘Access-Control-Allow-Origin’, ‘http://localhost:9099’)
    ctx.set(‘Access-Control-Allow-Credentials’, true)
    // 非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)
    // 这种情况下除了设置origin,还需要设置Access-Control-Request-Method以及Access-Control-Request-Headers
    ctx.set(‘Access-Control-Request-Method’, ‘PUT,POST,GET,DELETE,OPTIONS’)
    ctx.set(‘Access-Control-Allow-Headers’, ‘Origin, X-Requested-With, Content-Type, Accept, t’)
    ctx.cookies.set(‘tokenId’, ‘2’)
 
    ctx.body = successBody({msg: query.msg}, ‘success’)
  }
}
module.exports = CrossDomain

一个接口就要写这么多代码,假诺想有所接口都统一管理,有啥更优雅的不二等秘书技呢?见上边包车型地铁koa2-cors。

const path = require(‘path’) const Koa = require(‘koa’) const koaStatic
= require(‘koa-static’) const bodyParser = require(‘koa-bodyparser’)
const router = require(‘./router’) const cors = require(‘koa2-cors’)
const app = new Koa() const port = 9871 app.use(bodyParser()) //
管理静态财富 这里是前端build好之后的目录 app.use(koaStatic(
path.resolve(__dirname, ‘../dist’) )) // 处理cors app.use(cors({
origin: function (ctx) { return ” }, credentials:
true, allowMethods: [‘GET’, ‘POST’, ‘DELETE’], allowHeaders: [‘t’,
‘Content-Type’] })) // 路由
app.use(router.routes()).use(router.allowedMethods()) // 监听端口
app.listen(9871) console.log(`[demo] start-quick is starting at port
${port}`)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
const path = require(‘path’)
const Koa = require(‘koa’)
const koaStatic = require(‘koa-static’)
const bodyParser = require(‘koa-bodyparser’)
const router = require(‘./router’)
const cors = require(‘koa2-cors’)
const app = new Koa()
const port = 9871
app.use(bodyParser())
// 处理静态资源 这里是前端build好之后的目录
app.use(koaStatic(
  path.resolve(__dirname, ‘../dist’)
))
// 处理cors
app.use(cors({
  origin: function (ctx) {
    return ‘http://localhost:9099’
  },
  credentials: true,
  allowMethods: [‘GET’, ‘POST’, ‘DELETE’],
  allowHeaders: [‘t’, ‘Content-Type’]
}))
// 路由
app.use(router.routes()).use(router.allowedMethods())
// 监听端口
app.listen(9871)
console.log(`[demo] start-quick is starting at port ${port}`)
 

前端

fetch(`, { //
须要带上cookie credentials: ‘include’, //
这里增加额外的headers来触发非轻易需要 headers: { ‘t’: ‘extra headers’ }
}).then(res => { console.log(res) })

1
2
3
4
5
6
7
8
9
10
fetch(`http://localhost:9871/api/cors?msg=helloCors`, {
  // 需要带上cookie
  credentials: ‘include’,
  // 这里添加额外的headers来触发非简单请求
  headers: {
    ‘t’: ‘extra headers’
  }
}).then(res => {
  console.log(res)
})

4.代理
想转手,假诺大家呼吁的时候依旧用前端的域名,然后有个东西帮大家把那几个须要转载到确实的后端域名上,不就制止跨域了吗?那时候,Nginx出场了。
Nginx配置

server{ # 监听9099端口 listen 9099; # 域名是localhost server_name
localhost;
#凡是localhost:9099/api那么些样子的,都转载到确实的服务端地址
location ^~ /api { proxy_pass ; } }

1
2
3
4
5
6
7
8
9
10
server{
    # 监听9099端口
    listen 9099;
    # 域名是localhost
    server_name localhost;
    #凡是localhost:9099/api这个样子的,都转发到真正的服务端地址http://localhost:9871
    location ^~ /api {
        proxy_pass http://localhost:9871;
    }    
}

前端就毫无干什么职业了,除了写接口,也没后端什么事情了

//
伏乞的时候一贯用回前端那边的域名
fetch(”, { method: ‘POST’, headers:
{ ‘Accept’: ‘application/json’, ‘Content-Type’: ‘application/json’ },
body: JSON.stringify({ msg: ‘helloIframePost’ }) })

1
2
3
4
5
6
7
8
9
10
11
// 请求的时候直接用回前端这边的域名http://localhost:9099,这就不会跨域,然后Nginx监听到凡是localhost:9099/api这个样子的,都转发到真正的服务端地址http://localhost:9871
fetch(‘http://localhost:9099/api/iframePost’, {
  method: ‘POST’,
  headers: {
    ‘Accept’: ‘application/json’,
    ‘Content-Type’: ‘application/json’
  },
  body: JSON.stringify({
    msg: ‘helloIframePost’
  })
})

Nginx转载的点子就如很有益!但这种利用也是看现象的,要是后端接口是三个国有的API,举例一些公共服务获取天气什么的,前端调用的时候总不能够让运营去安顿一下Nginx,如若包容性没难题(IE
10要么以上),CROS才是更通用的做法呢。

同源战术限制下Dom查询的不易展开药形式

1.postMessage
window.postMessage()
是HTML5的一个接口,专注实现分歧窗口分化页面包车型大巴跨域通信。
为了演示方便,大家将hosts改一下:127.0.0.1
crossDomain.com,今后访问域名crossDomain.com就等于访谈127.0.0.1。

这里是:9099/#/crossDomain,发新闻方

JavaScript

<template> <div> <button
@click=”postMessage”>给;
<iframe name=”crossDomainIframe”
src=”; </div>
</template> <script> export default { mounted () {
window.addEventListener(‘message’, (e) => { // 这里一定要对来自做校验
if (e.origin === ”) { //
来自 console.log(e.data) } }) },
methods: { // 向 postMessage () { const
iframe = window.frames[‘crossDomainIframe’]
iframe.postMessage(‘我是[],
麻烦你查一下您那边有未有id为app的Dom’, ”) }
} } </script>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<template>
  <div>
    <button @click="postMessage">给http://crossDomain.com:9099发消息</button>
    <iframe name="crossDomainIframe" src="http://crossdomain.com:9099"></iframe>
  </div>
</template>
 
<script>
export default {
  mounted () {
    window.addEventListener(‘message’, (e) => {
      // 这里一定要对来源做校验
      if (e.origin === ‘http://crossdomain.com:9099’) {
        // 来自http://crossdomain.com:9099的结果回复
        console.log(e.data)
      }
    })
  },
  methods: {
    // 向http://crossdomain.com:9099发消息
    postMessage () {
      const iframe = window.frames[‘crossDomainIframe’]
      iframe.postMessage(‘我是[http://localhost:9099], 麻烦你查一下你那边有没有id为app的Dom’, ‘http://crossdomain.com:9099’)
    }
  }
}
</script>

这里是:9099,接收音信方

JavaScript

<template> <div> 我是
</div> </template> <script> export default { mounted
() { window.add伊芙ntListener(‘message’, (e) => { //
这里一定要对来源做校验 if (e.origin === ”) { //
console.log(e.data) //
e.source能够是回信的目的,其实正是
// e.origin可以作为targetOrigin
e.source.postMessage(`我是[‘)
? ‘有id为app的Dom’ : ‘没有id为app的Dom’}`, e.origin); } }) } }
</script>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
  <div>
    我是http://crossdomain.com:9099
  </div>
</template>
 
<script>
export default {
  mounted () {
    window.addEventListener(‘message’, (e) => {
      // 这里一定要对来源做校验
      if (e.origin === ‘http://localhost:9099’) {
        // http://localhost:9099发来的信息
        console.log(e.data)
        // e.source可以是回信的对象,其实就是http://localhost:9099窗口对象(window)的引用
        // e.origin可以作为targetOrigin
        e.source.postMessage(`我是[http://crossdomain.com:9099],我知道了兄弟,这就是你想知道的结果:${document.getElementById(‘app’) ? ‘有id为app的Dom’ : ‘没有id为app的Dom’}`, e.origin);
      }
    })
  }
}
</script>

结果能够阅览:

图片 2

2.document.domain
这种方法只适合主域名一样,但子域名分裂的iframe跨域。
比方说主域名是:9099,子域名是:9099,这种场所下给七个页面内定一下document.domain即document.domain
= crossdomain.com就能够访谈各自的window对象了。

3.canvas操作图片的跨域难题
本条理应是三个非常冰冷门的跨域难题,张大神已经写过了作者就不再班门弄斧了消除canvas图片getImageData,toDataULX570L跨域难点

最后

盼望看完那篇小说之后,再有人问跨域的主题材料,你能够嘴角微微上扬,冷笑一声:“不要再问小编跨域的难题了。”
甩手离去。

1 赞 6 收藏
评论

图片 3

相关文章