澳门新萄京官方网站-www.8455.com-澳门新萄京赌场网址

澳门新萄京官方网站:焚林而猎跨域的方案,不

2019-12-01 作者:澳门新萄京赌场网址   |   浏览(138)

永不再问俺跨域的标题了

2018/07/16 · 底子才具 · 跨域

初稿出处: 写Bug   

写下那篇文章后作者想,要不然后就把这种幼功的科学普及知识都归到那一个“不要再问小编XX的标题”,形成风华正茂各种内容,希望大家看完事后再有人问您那一个主题素材,你内心会窃喜:“嘿嘿,是时候展现真正的技巧了!”
一、不要再问小编this的照准难点了

跨域那三个字就疑似一块狗皮膏药同样黏在每二个前端开垦者身上,无论你在专业上大概面试中无可幸免会蒙受这些主题素材。为了敷衍面试,小编老是都不管背多少个方案,也不清楚为什么要如此干,反正面完就足以扔了,笔者想专门的学业上也不会用到那么多混淆黑白的方案。到了着进行事,开荒条件有webpack-dev-server化解,上线了服务端的大佬们也会配好,配了什么样笔者不管,反正不会跨域便是了。日子也就这么混过去了,终于有一天,小编认为不能再持续这么混下去了,小编决然要透顶搞懂那一个事物!于是就有了那篇小说。

前面二个层出不穷跨域解决方案(全)

2017/09/14 · 功底手艺 · 3 评论 · 跨域

初稿出处: 安静de沉淀   

什么是跨域?

何以是跨域?

要调整跨域,首先要明白为啥会有跨域那一个标题应时而生

真正,大家这种搬砖工人正是为着混口饭吃嘛,好好的调个接口告诉本身跨域了,这种阻碍大家轻松搬砖的专业真恶心!为何会跨域?是什么人在搞专门的职业?为了找到那一个主题素材的罪魁祸首,请点击浏览器的同源计谋。
如此那般官方的东西真难懂,没涉及,起码你领悟了,因为浏览器的同源战术招致了跨域,就是浏览器在搞工作。
由此,浏览器为什么要搞职业?正是不想给好日子大家过?对于这么的郁结,浏览器甩锅道:“同源攻略约束了从同多少个源加载的文书档案或脚本如何与来自另三个源的能源实行相互。那是叁个用来隔绝潜在恶意文件的入眼安全机制。”
如此那般官方的话术真难懂,没涉及,最少你精晓了,有如那是个平平安安机制。
据此,终归为何需求这样的安全体制?那样的平安体制化解了怎么着难题?别急,让我们再三再四研讨下去。

怎样是跨域?

跨域是指二个域下的文书档案或脚本筹划去乞请另一个域下的能源,这里跨域是广义的。

广义的跨域:

1.卡塔尔(英语:State of Qatar) 财富跳转: A链接、重定向、表单提交 2.卡塔尔资源嵌入:<link>、<script>、<img>、<frame>等dom标签,还应该有样式中background:url(卡塔尔(قطر‎、@font-face(卡塔尔(英语:State of Qatar)等公事外链 3.卡塔尔国 脚本央求: js发起的ajax须要、dom和js对象的跨域操作等

1
2
3
1.) 资源跳转: A链接、重定向、表单提交
2.) 资源嵌入:<link>、<script>、<img>、<frame>等dom标签,还有样式中background:url()、@font-face()等文件外链
3.) 脚本请求: js发起的ajax请求、dom和js对象的跨域操作等

实则大家日常所说的跨域是狭义的,是由浏览器同源计谋约束的意气风发类诉求场景。

何以是同源战术?
同源战略/SOP(萨姆e origin policy)是风流洒脱种约定,由Netscape集团一九九五年引进浏览器,它是浏览器最主题也最基本的金昌效用,如若缺乏了同源战术,浏览器超轻便遭逢XSS、CSF宝马7系等攻击。所谓同源是指”公约 域名 端口”三者风姿浪漫致,固然五个例外的域名指向同七个ip地址,也非同源。

同源计策节制之下两种行为:

1.卡塔尔(英语:State of Qatar) Cookie、LocalStorage 和 IndexDB 不恐怕读取 2.卡塔尔国 DOM 和 Js对象非常的小概获取 3.卡塔尔国 AJAX 乞请不能发送

1
2
3
1.) Cookie、LocalStorage 和 IndexDB 无法读取
2.) DOM 和 Js对象无法获得
3.) AJAX 请求不能发送

 

2.)资源嵌入:、、、等dom标签,还会有样式中background:url(卡塔尔(قطر‎、@font-face(卡塔尔等文件外链

未有同源计谋限定的两大危急景况

据本身询问,浏览器是从两个方面去做那些同源战略的,一是指向接口的伸手,二是针对Dom的查询。试想一下不曾如此的限量上述三种动作有何危殆。

科学普及跨域场景

U本田CR-VL 表达 是或不是同意通讯 同豆蔻梢头域名,区别文件或路线 允许 同黄金时代域名,差别端口 不容许 同少年老成域名,差别协商 不容许 域名和域名对应相符ip 不容许 主域相通,子域不相同不容许 差异域名 不准

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
URL                                      说明                    是否允许通信
http://www.domain.com/a.js
http://www.domain.com/b.js         同一域名,不同文件或路径           允许
http://www.domain.com/lab/c.js
 
http://www.domain.com:8000/a.js
http://www.domain.com/b.js         同一域名,不同端口                不允许
http://www.domain.com/a.js
https://www.domain.com/b.js        同一域名,不同协议                不允许
http://www.domain.com/a.js
http://192.168.4.12/b.js           域名和域名对应相同ip              不允许
http://www.domain.com/a.js
http://x.domain.com/b.js           主域相同,子域不同                不允许
http://domain.com/c.js
http://www.domain1.com/a.js
http://www.domain2.com/b.js        不同域名                         不允许

跨域是指四个域下的文书档案或脚本酌量去乞求另叁个域下的能源,这里跨域是广义的。

3.卡塔尔国 脚本供给: js发起的ajax须求、dom和js对象的跨域操作等

尚无同源策略限定的接口央求

有叁个超小的事物叫cookie咱们应该理解,平日用来处理登陆等处境,目标是让服务端知道哪个人发出的此次须要。倘让你乞请了接口进行登陆,服务端验证通过后会在响应头出席Set-Cookie字段,然后下一次再发请求的时候,浏览器会活动将cookie附加在HTTP央浼的头字段库克ie中,服务端就能够明了那个客户已经报到过了。知道这几个将来,大家来看现象:
1.您绸缪去清空你的购物车,于是展开了买买买网址www.maimaimai.com,然后登陆成功,意气风发看,购物车东西如此少,不行,还得买多点。
2.您在看有何事物买的经过中,你的好好友发给你一个链接www.nidongde.com,一脸yin笑地跟你说:“你懂的”,你坚决张开了。
3.你兴趣盎然地浏览着www.nidongde.com,哪个人知那一个网址暗地里做了些不可描述的事情!由于未有同源战术的界定,它向www.maimaimai.com发起了必要!聪明的您一定想到上边的话“服务端验证通过后会在响应头参预Set-Cookie字段,然后后一次再发央求的时候,浏览器会活动将cookie附加在HTTP央浼的头字段Cookie中”,那样一来,那一个地下网站就一定于登陆了你的账号,可认为所欲为了!固然那不是叁个买买买账号,而是你的银行账号,那……
那就是风传中的CSEvoqueF攻击浅谈CSLANDF攻击方式。
看了这波CS本田CR-VF攻击小编在想,纵然有了同源战术节制,但cookie是真心实意的,还不是一模二样能拿下来。于是小编看了部分cookie相关的篇章聊一聊 cookie、Cookie/Session的建制与铜川,知道了服务端能够安装httpOnly,使得前端无法操作cookie,纵然没有如此的安装,像XSS攻击就能够去赢拿到cookieWeb安全测量试验之XSS;设置secure,则保障在https的加密通讯中传输避防截获。

跨域施工方案

1、 通过jsonp跨域
2、 document.domain iframe跨域
3、 location.hash iframe
4、 window.name iframe跨域
5、 postMessage跨域
6、 跨域财富分享(COLX570S)
7、 nginx代理跨域
8、 nodejs中间件代理跨域
9、 WebSocket磋商跨域

 

骨子里大家见惯司空所说的跨域是狭义的,是由浏览器同源计策节制的生龙活虎类央浼场景。

从未同源战术约束的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'卡塔尔(英语:State of Qatar)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},我还拿不到你刚刚输入的账号密码吗`)

由此大家通晓,同源战略确实能回避一些摇摇欲堕,不是说有了同源战略就安全,只是说同源计策是生机勃勃种浏览器最大旨的平安体制,毕竟能增加一点抨击的资金财产。其实未有刺不穿的盾,只是攻击的本金和抨击成功后获得的裨益成不成正比。

一、 通过jsonp跨域

习见为了减轻web服务器的负载,大家把js、css,img等静态能源剥离到另风姿洒脱台独立域名的服务器上,在html页面中再经过相应的标签从分化域名下加载静态财富,而被浏览器允许,基于此原理,我们得以透过动态创制script,再央浼叁个带参网站完成跨域通讯。

1.)原生完毕:

<script> var script = document.createElement('script'卡塔尔(英语:State of Qatar); script.type = 'text/javascript'; // 传参并钦命回调施行函数为onBack script.src = ''; document.head.appendChild(script卡塔尔(英语:State of Qatar); // 回调推行函数 function onBack(res卡塔尔(英语:State of Qatar){ alert(JSON.stringify(res卡塔尔(英语:State of Qatar)卡塔尔国; } </script>

1
2
3
4
5
6
7
8
9
10
11
12
13
<script>
    var script = document.createElement('script');
    script.type = 'text/javascript';
 
    // 传参并指定回调执行函数为onBack
    script.src = 'http://www.domain2.com:8080/login?user=admin&callback=onBack';
    document.head.appendChild(script);
 
    // 回调执行函数
    function onBack(res) {
        alert(JSON.stringify(res));
    }
</script>

服务端再次回到如下(再次回到时即进行全局函数):

onBack({"status": true, "user": "admin"})

1
onBack({"status": true, "user": "admin"})

2.)jquery ajax:

$.ajax({ url: '', type: 'get', dataType: 'jsonp', // 央求情势为jsonp jsonpCallback: "onBack", // 自定义回调函数名 data: {} }卡塔尔(英语:State of Qatar);

1
2
3
4
5
6
7
$.ajax({
    url: 'http://www.domain2.com:8080/login',
    type: 'get',
    dataType: 'jsonp',  // 请求方式为jsonp
    jsonpCallback: "onBack",    // 自定义回调函数名
    data: {}
});

3.)vue.js:

this.$http.jsonp('', { params: {}, jsonp: 'onBack' }).then((res) => { console.log(res); })

1
2
3
4
5
6
this.$http.jsonp('http://www.domain2.com:8080/login', {
    params: {},
    jsonp: 'onBack'
}).then((res) => {
    console.log(res);
})

后端node.js代码示例:

var querystring = require('querystring'); var http = require('http'); var server = http.createServer(); server.on('request', function(req, res) { var params = qs.parse(req.url.split('?')[1]卡塔尔(英语:State of Qatar); var fn = params.callback; // jsonp重回设置 res.writeHead(200, { 'Content-Type': 'text/javascript' }卡塔尔; res.write(fn '(' JSON.stringify(params卡塔尔(قطر‎ '卡塔尔'卡塔尔(قطر‎; res.end(卡塔尔(英语:State of Qatar); }卡塔尔(قطر‎; server.listen('8080'卡塔尔(قطر‎; console.log('Server is running at port 8080...'卡塔尔;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var querystring = require('querystring');
var http = require('http');
var server = http.createServer();
 
server.on('request', function(req, res) {
    var params = qs.parse(req.url.split('?')[1]);
    var fn = params.callback;
 
    // jsonp返回设置
    res.writeHead(200, { 'Content-Type': 'text/javascript' });
    res.write(fn '(' JSON.stringify(params) ')');
 
    res.end();
});
 
server.listen('8080');
console.log('Server is running at port 8080...');

jsonp短处:只好促成get生机勃勃种央浼。

广义的跨域:

什么是同源战略?

跨域正确的张开药格局

透过对同源战术的询问,大家相应要免除对浏览器的误解,同源战略是浏览器做的风度翩翩件善事,是用来防卫来自旁门左道的口诛笔伐,但总无法为了不让败类进门而把全部人都拒人千里之外呢。没有错,大家这种正派人物只要张开药方式正确,就应有能够跨域。
下边将二个个示范正确张开方式,但早前,有个别计划干活要做。为了本地演示跨域,大家需求:
1.随意跑起生龙活虎份前端代码(以下前端是随意跑起来的vue),地址是:9099。
2.随意跑起意气风发份后端代码(以下后端是随便跑起来的node koa2),地址是:9971。

二、 document.domain iframe跨域

此方案只限主域相似,子域不一样的跨域应用处景。

达成原理:三个页面都经过js强制设置document.domain为底蕴主域,就落到实处了同域。

1.)父窗口:(

<iframe id="iframe" src="; <script> document.domain = 'domain.com'; var user = 'admin'; </script>

1
2
3
4
5
<iframe id="iframe" src="http://child.domain.com/b.html"></iframe>
<script>
    document.domain = 'domain.com';
    var user = 'admin';
</script>

2.)子窗口:(

<script> document.domain = 'domain.com'; // 获取父窗口中变量 alert('get js data from parent ---> ' window.parent.user卡塔尔(英语:State of Qatar); </script>

1
2
3
4
5
<script>
    document.domain = 'domain.com';
    // 获取父窗口中变量
    alert('get js data from parent ---> ' window.parent.user);
</script>

 

同源计谋/SOP(山姆e origin policy)是生机勃勃种约定,由Netscape公司壹玖玖叁年引进浏览器,它是浏览器最基本也最基本的乌海功效,假诺贫乏了同源计策,浏览器十分轻巧受到XSS、CSF帕杰罗等攻击。所谓同源是指”左券 域名 端口”三者风流倜傥致,就算八个分裂的域名指向同一个ip地址,也非同源。

同源计谋节制下接口诉求的不利张开药方式

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'卡塔尔(英语:State of Qatar) // 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卡塔尔(英语:State of Qatar) => { // 处理传参成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卡塔尔(英语:State of Qatar) => { document.body.removeChild(script卡塔尔国 delete window.jsonpCb resolve(res卡塔尔(قطر‎ } script.src = `${url}?${handleData(data)}&cb=jsonpCb` document.body.appendChild(script卡塔尔(英语:State of Qatar) }卡塔尔 } // 使用方式 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卡塔尔(英语:State of Qatar) { 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'卡塔尔(英语:State of Qatar) const node = document.createElement('input'卡塔尔(英语:State of Qatar) // 注册iframe的load事件管理程序,假使您供给在响应重回时举行一些操作的话. iframe.add伊夫ntListener('load', function (卡塔尔(英语:State of Qatar) { console.log('post success'卡塔尔(英语:State of Qatar) }卡塔尔(英语:State of Qatar) form.action = url // 在钦赐的iframe中奉行form form.target = iframe.name form.method = 'post' for (let name in data卡塔尔(英语:State of Qatar) { 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)跨域财富分享 CO中华VS 安详严整。看名字就知晓那是管理跨域难点的专门的职业做法。COOdysseyS有两种央求,简单诉求和非简单诉求。

这里引用上边链接阮一峰先生的小说证实一下简邀诉求和非简单诉求。
浏览器将CO大切诺基S诉求分成两类:容易央求(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'卡塔尔(英语:State of Qatar)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景逸SUVS央浼,会在正规通讯早先,增添一遍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'卡塔尔(英语:State of Qatar) const koaStatic = require('koa-static'卡塔尔 const bodyParser = require('koa-bodyparser'卡塔尔国const router = require('./router'卡塔尔(قطر‎ const cors = require('koa2-cors'卡塔尔(قطر‎const app = new Koa(卡塔尔(英语:State of Qatar) const port = 9871 app.use(bodyParser(卡塔尔(英语:State of Qatar)卡塔尔 // 管理静态能源 这里是前端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(卡塔尔(قطر‎卡塔尔(英语:State of Qatar).use(router.allowedMethods(卡塔尔卡塔尔(英语:State of Qatar) // 监听端口 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卡塔尔(英语:State of Qatar) }卡塔尔国

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才是更通用的做法呢。

三、 location.hash iframe跨域

兑现原理: a欲与b跨域相互通讯,通过中间页c来贯彻。 多个页面,分歧域之间接纳iframe的location.hash传值,相符域之间平素js访问来通信。

切切实实贯彻:A域:a.html -> B域:b.html -> A域:c.html,a与b不相同域只可以通过hash值单向通讯,b与c也不相同域也只好单向通讯,但c与a同域,所以c可通过parent.parent采访a页面全数目的。

1.)a.html:(

<iframe id="iframe" src="" style="display:none;"></iframe> <script>     var iframe = document.getElementById('iframe');     // 向b.html传hash值     setTimeout(function() {         iframe.src = iframe.src '#user=admin';     }, 1000卡塔尔;          // 开放给同域c.html的回调方法     function onCallback(res卡塔尔 {         alert('data from c.html ---> ' res卡塔尔;     } </script>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<iframe id="iframe" src="http://www.domain2.com/b.html" style="display:none;"></iframe&gt
<script>
    var iframe = document.getElementById('iframe');
 
    // 向b.html传hash值
    setTimeout(function() {
        iframe.src = iframe.src '#user=admin';
    }, 1000);
    
    // 开放给同域c.html的回调方法
    function onCallback(res) {
        alert('data from c.html ---> ' res);
    }
</script>

2.)b.html:(

<iframe id="iframe" src="" style="display:none;"></iframe> <script>     var iframe = document.getElementById('iframe');     // 监听a.html传来的hash值,再传给c.html     window.onhashchange = function () {         iframe.src = iframe.src location.hash;     }; </script>

1
2
3
4
5
6
7
8
9
<iframe id="iframe" src="http://www.domain1.com/c.html" style="display:none;"></iframe>
<script>
    var iframe = document.getElementById('iframe');
 
    // 监听a.html传来的hash值,再传给c.html
    window.onhashchange = function () {
        iframe.src = iframe.src location.hash;
    };
</script>

3.)c.html:(

<script>     // 监听b.html传来的hash值     window.onhashchange = function (卡塔尔 {         // 再通过操作同域a.html的js回调,将结果传到         window.parent.parent.onCallback('hello: ' location.hash.replace('#user=', ''));     }; </script>

1
2
3
4
5
6
7
<script>
    // 监听b.html传来的hash值
    window.onhashchange = function () {
        // 再通过操作同域a.html的js回调,将结果传回
        window.parent.parent.onCallback('hello: ' location.hash.replace('#user=', ''));
    };
</script>

1.卡塔尔国 能源跳转: A链接、重定向、表单提交

同源攻略约束之下二种行为:

同源计策限定下Dom查询的没有错展开方式

1.postMessage
window.postMessage(卡塔尔(英语:State of Qatar)是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.add伊芙ntListener('message', (e卡塔尔(英语:State of Qatar) => { // 这里确定要对来源做校验 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.addEventListener('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,toDataU福特ExplorerL跨域难点

四、 window.name iframe跨域

window.name属性的优质之处:name值在分歧的页面(以致区别域名)加载后依然存在,而且能够扶助极度长的 name 值(2MB)。

1.)a.html:(

var proxy = function(url, callback卡塔尔(قطر‎ { var state = 0; var iframe = document.createElement('iframe'卡塔尔(قطر‎; // 加载跨域页面 iframe.src = url; // onload事件会触发2次,第1次加载跨域页,并设有数据于window.name iframe.onload = function(卡塔尔(قطر‎ { if (state === 1卡塔尔 { // 第2次onload(同域proxy页卡塔尔国成功后,读取同域window.name中多少 callback(iframe.contentWindow.name卡塔尔; destoryFrame(卡塔尔(英语:State of Qatar); } else if (state === 0卡塔尔(英语:State of Qatar) { // 第1次onload(跨域页卡塔尔国成功后,切换来同域代理页面 iframe.contentWindow.location = ''; state = 1; } }; document.body.appendChild(iframe卡塔尔(英语:State of Qatar); // 获取数据以往销毁那几个iframe,释放内部存款和储蓄器;那也保险了安全(不被此外域frame js访谈) function destoryFrame() { iframe.contentWindow.document.write(''卡塔尔国; iframe.contentWindow.close(卡塔尔(英语:State of Qatar); document.body.removeChild(iframe卡塔尔国; } }; // 央求跨域b页面数据 proxy('', function(data){ alert(data); });

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
var proxy = function(url, callback) {
    var state = 0;
    var iframe = document.createElement('iframe');
 
    // 加载跨域页面
    iframe.src = url;
 
    // onload事件会触发2次,第1次加载跨域页,并留存数据于window.name
    iframe.onload = function() {
        if (state === 1) {
            // 第2次onload(同域proxy页)成功后,读取同域window.name中数据
            callback(iframe.contentWindow.name);
            destoryFrame();
 
        } else if (state === 0) {
            // 第1次onload(跨域页)成功后,切换到同域代理页面
            iframe.contentWindow.location = 'http://www.domain1.com/proxy.html';
            state = 1;
        }
    };
 
    document.body.appendChild(iframe);
 
    // 获取数据以后销毁这个iframe,释放内存;这也保证了安全(不被其他域frame js访问)
    function destoryFrame() {
        iframe.contentWindow.document.write('');
        iframe.contentWindow.close();
        document.body.removeChild(iframe);
    }
};
 
// 请求跨域b页面数据
proxy('http://www.domain2.com/b.html', function(data){
    alert(data);
});

2.)proxy.html:(http://www.domain1.com/proxy….)
个中代理页,与a.html同域,内容为空就能够。

3.)b.html:(

<script>     window.name = 'This is domain2 data!'; </script>

1
2
3
<script>
    window.name = 'This is domain2 data!';
</script>

总计:通过iframe的src属性由国外转向本地点,跨域数据即由iframe的window.name从海外传递到当地方。那么些就高明地绕过了浏览器的跨域访谈限定,但还要它又是安全操作。

2.卡塔尔国能源嵌入:<link>、<script>、<img>、<frame>等dom标签,还应该有样式中background:url(卡塔尔(قطر‎、@font-face(卡塔尔(英语:State of Qatar)等文件外链

1.卡塔尔国 Cookie、LocalStorage 和 IndexDB 不可能读取

最后

目的在于看完那篇小说之后,再有人问跨域的主题素材,你可以嘴角微微上扬,冷笑一声:“不要再问作者跨域的难点了。”
扬长而去。

1 赞 6 收藏 评论

澳门新萄京官方网站 3

五、 postMessage跨域

postMessage是HTML5 XMLHttpRequest Level 第22中学的API,且是为数非常少能够跨域操作的window属性之风流洒脱,它可用于消除以下方面包车型客车主题材料:
a.) 页面和其开发的新窗口的数据传递
b.) 多窗口之间音信传递
c.) 页面与嵌套的iframe信息传递
d.) 下边七个现象的跨域数据传递

用法:postMessage(data,origin卡塔尔(قطر‎方法接受多个参数
data: html5正规扶植大肆基本项目或可复制的指标,但某些浏览器只援救字符串,所以传参时最佳用JSON.stringify(卡塔尔国类别化。
origin: 公约 主机 端口号,也得以设置为”*”,表示能够传递给自由窗口,假使要钦定和如今窗口同源的话设置为”/”。

1.)a.html:(

<iframe id="iframe" src="" style="display:none;"></iframe> <script> var iframe = document.getElementById('iframe'卡塔尔; iframe.onload = function(卡塔尔(英语:State of Qatar) { var data = { name: 'aym' }; // 向domain2传送跨域数据 iframe.contentWindow.postMessage(JSON.stringify(data卡塔尔, ''卡塔尔; }; // 选取domain2再次来到数据 window.addEventListener('message', function(e卡塔尔 { alert('data from domain2 ---> ' e.data卡塔尔(英语:State of Qatar); }, false卡塔尔; </script>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<iframe id="iframe" src="http://www.domain2.com/b.html" style="display:none;"></iframe>
<script>      
    var iframe = document.getElementById('iframe');
    iframe.onload = function() {
        var data = {
            name: 'aym'
        };
        // 向domain2传送跨域数据
        iframe.contentWindow.postMessage(JSON.stringify(data), 'http://www.domain2.com');
    };
 
    // 接受domain2返回数据
    window.addEventListener('message', function(e) {
        alert('data from domain2 ---> ' e.data);
    }, false);
</script>

2.)b.html:(

<script> // 接受domain1的数码 window.add伊芙ntListener('message', function(e卡塔尔 { alert('data from domain1 ---> ' e.data卡塔尔(英语:State of Qatar); var data = JSON.parse(e.data卡塔尔(قطر‎; if (data卡塔尔国 { data.number = 16; // 处理后再发回domain1 window.parent.postMessage(JSON.stringify(data卡塔尔(قطر‎, ''); } }, false); </script>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script>
    // 接收domain1的数据
    window.addEventListener('message', function(e) {
        alert('data from domain1 ---> ' e.data);
 
        var data = JSON.parse(e.data);
        if (data) {
            data.number = 16;
 
            // 处理后再发回domain1
            window.parent.postMessage(JSON.stringify(data), 'http://www.domain1.com');
        }
    }, false);
</script>

3.卡塔尔(قطر‎ 脚本诉求: js发起的ajax央浼、dom和js对象的跨域操作等

2.卡塔尔国 DOM 和 Js对象不可能获得

六、 跨域能源共享(COWranglerS)

不乏先例跨域请求:只服务端设置Access-Control-Allow-Origin就能够,前端无须设置。
带cookie乞求:前后端都亟待设置字段,此外部必要注意:所带cookie为跨域伏乞接口所在域的cookie,而非当前页。
现阶段,全体浏览器都扶植该意义(IE8 :IE8/9急需运用XDomainRequest对象来扶植COPRADOS)卡塔尔(قطر‎,COLANDS也早就改成主流的跨域设计方案。

 

3.卡塔尔(قطر‎ AJAX 央浼不可能发送

1、 前端设置:

1.)原生ajax

// 前端安装是不是带cookie xhr.withCredentials = true;

1
2
// 前端设置是否带cookie
xhr.withCredentials = true;

演示代码:

var xhr = new XMLHttpRequest(卡塔尔(قطر‎; // IE8/9需用window.XDomainRequest包容 // 前端安装是不是带cookie xhr.withCredentials = true; xhr.open('post', '', true); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.send('user=admin'); xhr.onreadystatechange = function() { if (xhr.readyState == 4 && xhr.status == 200) { alert(xhr.responseText); } };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容
 
// 前端设置是否带cookie
xhr.withCredentials = true;
 
xhr.open('post', 'http://www.domain2.com:8080/login', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('user=admin');
 
xhr.onreadystatechange = function() {
    if (xhr.readyState == 4 && xhr.status == 200) {
        alert(xhr.responseText);
    }
};

2.)jQuery ajax

$.ajax({ ... xhrFields: { withCredentials: true // 前端安装是还是不是带cookie }, crossDomain: true, // 会让乞请头中满含跨域的额外消息,但不会含cookie ... }卡塔尔(英语:State of Qatar);

1
2
3
4
5
6
7
8
$.ajax({
    ...
   xhrFields: {
       withCredentials: true    // 前端设置是否带cookie
   },
   crossDomain: true,   // 会让请求头中包含跨域的额外信息,但不会含cookie
    ...
});

3.)vue框架
在vue-resource封装的ajax组件中步向以下代码:

Vue.http.options.credentials = true

1
Vue.http.options.credentials = true

实质上大家普通所说的跨域是狭义的,是由浏览器同源计策约束的后生可畏类央浼场景。

多如牛毛跨域场景

2、 服务端设置:

若后端设置成功,前端浏览器调控台则不会并发跨域报错新闻,反之,表达没设成功。

1.)Java后台:

/* * 导入包:import javax.servlet.http.HttpServletResponse; * 接口参数中定义:HttpServletResponse response */ response.setHeader("Access-Control-Allow-Origin", ""卡塔尔; // 若有端口需写全(左券 域名 端口) response.setHeader("Access-Control-Allow-Credentials", "true"卡塔尔(قطر‎;

1
2
3
4
5
6
/*
* 导入包:import javax.servlet.http.HttpServletResponse;
* 接口参数中定义:HttpServletResponse response
*/
response.setHeader("Access-Control-Allow-Origin", "http://www.domain1.com");  // 若有端口需写全(协议 域名 端口)
response.setHeader("Access-Control-Allow-Credentials", "true");

2.)Nodejs后台示例:

var http = require('http'卡塔尔(قطر‎; var server = http.createServer(卡塔尔; var qs = require('querystring'卡塔尔(英语:State of Qatar); server.on('request', function(req, res卡塔尔 { var postData = ''; // 数据块接受中 req.addListener('data', function(chunk卡塔尔(英语:State of Qatar) { postData = chunk; }卡塔尔(英语:State of Qatar); // 数据选取完结 req.addListener('end', function(){ postData = qs.parse(postData卡塔尔国; // 跨域后台装置 res.writeHead(200, { 'Access-Control-Allow-Credentials': 'true', // 后端允许发送Cookie 'Access-Control-Allow-Origin': '', // 允许访问的域(契约 域名 端口) 'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly' // HttpOnly:脚本不能读取cookie }卡塔尔(قطر‎; res.write(JSON.stringify(postData卡塔尔(قطر‎卡塔尔; res.end(卡塔尔国; }卡塔尔(قطر‎; }卡塔尔; server.listen('8080'卡塔尔; console.log('Server is running at port 8080...'卡塔尔(英语:State of Qatar);

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
var http = require('http');
var server = http.createServer();
var qs = require('querystring');
 
server.on('request', function(req, res) {
    var postData = '';
 
    // 数据块接收中
    req.addListener('data', function(chunk) {
        postData = chunk;
    });
 
    // 数据接收完毕
    req.addListener('end', function() {
        postData = qs.parse(postData);
 
        // 跨域后台设置
        res.writeHead(200, {
            'Access-Control-Allow-Credentials': 'true',     // 后端允许发送Cookie
            'Access-Control-Allow-Origin': 'http://www.domain1.com',    // 允许访问的域(协议 域名 端口)
            'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly'   // HttpOnly:脚本无法读取cookie
        });
 
        res.write(JSON.stringify(postData));
        res.end();
    });
});
 
server.listen('8080');
console.log('Server is running at port 8080...');

 

UGL450L表明是或不是允许通讯

七、 nginx代理跨域

怎么样是同源计策?

1、 nginx配置化解iconfont跨域

浏览器跨域访谈js、css、img等正规静态能源被同源攻略获准,但iconfont字体文件(eot|otf|ttf|woff|svg卡塔尔(قطر‎例外,当时可在nginx的静态财富服务器中加入以下配置。

location / { add_header Access-Control-Allow-Origin *; }

1
2
3
location / {
  add_header Access-Control-Allow-Origin *;
}

 

         同意气风发域名,差异文件或路线           允许

2、 nginx反向代理接口跨域

跨域原理: 同源攻略是浏览器的安全攻略,不是HTTP协议的生机勃勃有些。服务器端调用HTTP接口只是利用HTTP合同,不会推行JS脚本,没有必要同源计策,也就不设有越过难点。

落到实处思路:通过nginx配置多个代理服务器(域名与domain1近似,端口分化)做跳板机,反向代理访问domain2接口,并且能够顺便校正cookie中domain音信,方便当前域cookie写入,完结跨域登陆。

nginx具体布置:

#proxy服务器 server { listen 81; server_name www.domain1.com; location / { proxy_pass ; #反向代理 proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie里域名 index index.html index.htm; # 当用webpack-dev-server等中间件代理接口访谈nignx时,那时候无浏览器加入,故并未有同源限定,上面包车型大巴跨域配置可不启用 add_header Access-Control-Allow-Origin ; #时下端只跨域不带cookie时,可为* add_header Access-Control-Allow-Credentials true; } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#proxy服务器
server {
    listen       81;
    server_name  www.domain1.com;
 
    location / {
        proxy_pass   http://www.domain2.com:8080;  #反向代理
        proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie里域名
        index  index.html index.htm;
 
        # 当用webpack-dev-server等中间件代理接口访问nignx时,此时无浏览器参与,故没有同源限制,下面的跨域配置可不启用
        add_header Access-Control-Allow-Origin http://www.domain1.com;  #当前端只跨域不带cookie时,可为*
        add_header Access-Control-Allow-Credentials true;
    }
}

1.卡塔尔(英语:State of Qatar) 前端代码示例:

var xhr = new XMLHttpRequest(卡塔尔(英语:State of Qatar); // 前端按键:浏览器是还是不是读写cookie xhr.withCredentials = true; // 访问nginx中的代理服务器 xhr.open('get', '', true); xhr.send();

1
2
3
4
5
6
7
8
var xhr = new XMLHttpRequest();
 
// 前端开关:浏览器是否读写cookie
xhr.withCredentials = true;
 
// 访问nginx中的代理服务器
xhr.open('get', 'http://www.domain1.com:81/?user=admin', true);
xhr.send();

2.卡塔尔国 Nodejs后台示例:

var http = require('http'卡塔尔; var server = http.createServer(卡塔尔国; var qs = require('querystring'卡塔尔(قطر‎; server.on('request', function(req, res卡塔尔(قطر‎ { var params = qs.parse(req.url.substring(2卡塔尔(英语:State of Qatar)卡塔尔(英语:State of Qatar); // 向前台写cookie res.writeHead(200, { 'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly' // HttpOnly:脚本不可能读取 }卡塔尔(قطر‎; res.write(JSON.stringify(params卡塔尔(قطر‎卡塔尔(قطر‎; res.end(卡塔尔(قطر‎; }卡塔尔国; server.listen('8080'卡塔尔; console.log('Server is running at port 8080...'卡塔尔国;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var http = require('http');
var server = http.createServer();
var qs = require('querystring');
 
server.on('request', function(req, res) {
    var params = qs.parse(req.url.substring(2));
 
    // 向前台写cookie
    res.writeHead(200, {
        'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly'   // HttpOnly:脚本无法读取
    });
 
    res.write(JSON.stringify(params));
    res.end();
});
 
server.listen('8080');
console.log('Server is running at port 8080...');

同源战术/SOP(Same origin policy)是生龙活虎种约定,由Netscape集团1994年引进浏览器,它是浏览器最基本也最基本的张家界功用,假使缺点和失误了同源攻略,浏览器比较轻巧碰着XSS、CSF路虎极光等攻击。所谓同源是指”左券 域名 端口”三者后生可畏致,即使八个例外的域名指向同贰个ip地址,也非同源。

八、 Nodejs中间件代理跨域

node中间件实现跨域代理,原理大约与nginx相像,都以由此启三个代理服务器,达成数量的倒车。

 

1、 非vue框架的跨域(2次跨域)

应用node express http-proxy-middleware搭建一个proxy服务器。

1.)前端代码示例:

var xhr = new XMLHttpRequest(卡塔尔; // 前端开关:浏览器是或不是读写cookie xhr.withCredentials = true; // 访谈http-proxy-middleware代理服务器 xhr.open('get', '', true); xhr.send();

1
2
3
4
5
6
7
8
var xhr = new XMLHttpRequest();
 
// 前端开关:浏览器是否读写cookie
xhr.withCredentials = true;
 
// 访问http-proxy-middleware代理服务器
xhr.open('get', 'http://www.domain1.com:3000/login?user=admin', true);
xhr.send();

2.)中间件服务器:

var express = require('express'卡塔尔国; var proxy = require('http-proxy-middleware'卡塔尔; var app = express(卡塔尔(قطر‎; app.use('/', proxy({ // 代理跨域指标接口 target: '', changeOrigin: true, // 修正响应头音讯,达成跨域并允许带cookie onProxyRes: function(proxyRes, req, res卡塔尔国 { res.header('Access-Control-Allow-Origin', ''卡塔尔国; res.header('Access-Control-Allow-Credentials', 'true'卡塔尔国; }, // 改进响应新闻中的cookie域名 cookieDomainRewrite: 'www.domain1.com' // 可感觉false,表示不更正 })卡塔尔; app.listen(3000卡塔尔(قطر‎; console.log('Proxy server is listen at port 3000...'卡塔尔(英语:State of Qatar);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var express = require('express');
var proxy = require('http-proxy-middleware');
var app = express();
 
app.use('/', proxy({
    // 代理跨域目标接口
    target: 'http://www.domain2.com:8080',
    changeOrigin: true,
 
    // 修改响应头信息,实现跨域并允许带cookie
    onProxyRes: function(proxyRes, req, res) {
        res.header('Access-Control-Allow-Origin', 'http://www.domain1.com');
        res.header('Access-Control-Allow-Credentials', 'true');
    },
 
    // 修改响应信息中的cookie域名
    cookieDomainRewrite: 'www.domain1.com'  // 可以为false,表示不修改
}));
 
app.listen(3000);
console.log('Proxy server is listen at port 3000...');

3.)Nodejs后台同(六:nginx)

同源计谋约束之下二种行为:

         同豆蔻梢头域名,区别端口                不许

2、 vue框架的跨域(1次跨域)

应用node webpack webpack-dev-server代理接口跨域。在付出境况下,由于vue渲染服务和接口代理服务都以webpack-dev-server同叁个,所以页面与代理接口之间不再跨域,无须设置headers跨域消息了。

webpack.config.js部分配置:

module.exports = { entry: {}, module: {}, ... devServer: { historyApiFallback: true, proxy: [{ context: '/login', target: '', // 代理跨域指标接口 changeOrigin: true, cookieDomainRewrite: 'www.domain1.com' // 可感觉false,表示不更改 }], noInfo: true } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module.exports = {
    entry: {},
    module: {},
    ...
    devServer: {
        historyApiFallback: true,
        proxy: [{
            context: '/login',
            target: 'http://www.domain2.com:8080',  // 代理跨域目标接口
            changeOrigin: true,
            cookieDomainRewrite: 'www.domain1.com'  // 可以为false,表示不修改
        }],
        noInfo: true
    }
}

 

九、 WebSocket协商跨域

WebSocket protocol是HTML5蓬蓬勃勃种新的商业事务。它实现了浏览器与服务器全双工通讯,同时同意跨域通讯,是server push技艺的生龙活虎种很好的落成。
原生WebSocket API使用起来不太有利,大家接收Socket.io,它很好地包裹了webSocket接口,提供了更简便易行、灵活的接口,也对不帮衬webSocket的浏览器提供了向下宽容。

1.)前端代码:

<div>user input:<input type="text"></div> <script src="./socket.io.js"></script> <script> var socket = io(''卡塔尔; // 连接成功拍卖 socket.on('connect', function(卡塔尔国 { // 监听服务端消息 socket.on('message', function(msg卡塔尔(英语:State of Qatar) { console.log('data from server: ---> ' msg卡塔尔; }卡塔尔(英语:State of Qatar); // 监听服务端关闭 socket.on('disconnect', function(卡塔尔(英语:State of Qatar) { console.log('Server socket has closed.'卡塔尔(قطر‎; }卡塔尔(英语:State of Qatar); }卡塔尔(قطر‎; document.getElementsByTagName('input'卡塔尔[0].onblur = function() { socket.send(this.value); }; </script>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<div>user input:<input type="text"></div>
<script src="./socket.io.js"></script>
<script>
var socket = io('http://www.domain2.com:8080');
 
// 连接成功处理
socket.on('connect', function() {
    // 监听服务端消息
    socket.on('message', function(msg) {
        console.log('data from server: ---> ' msg);
    });
 
    // 监听服务端关闭
    socket.on('disconnect', function() {
        console.log('Server socket has closed.');
    });
});
 
document.getElementsByTagName('input')[0].onblur = function() {
    socket.send(this.value);
};
</script>

2.)Nodejs socket后台:

var http = require('http'卡塔尔国; var socket = require('socket.io'卡塔尔国; // 启http服务 var server = http.createServer(function(req, res卡塔尔国 { res.writeHead(200, { 'Content-type': 'text/html' }卡塔尔; res.end(卡塔尔; }卡塔尔; server.listen('8080'卡塔尔; console.log('Server is running at port 8080...'卡塔尔国; // 监听socket连接 socket.listen(server卡塔尔国.on('connection', function(client卡塔尔(英语:State of Qatar) { // 接受消息 client.on('message', function(msg卡塔尔国 { client.send('hello:' msg卡塔尔; console.log('data from client: ---> ' msg卡塔尔; }卡塔尔国; // 断开管理 client.on('disconnect', function(卡塔尔国 { console.log('Client socket has closed.'卡塔尔(英语:State of Qatar); }卡塔尔(قطر‎; }卡塔尔;

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
var http = require('http');
var socket = require('socket.io');
 
// 启http服务
var server = http.createServer(function(req, res) {
    res.writeHead(200, {
        'Content-type': 'text/html'
    });
    res.end();
});
 
server.listen('8080');
console.log('Server is running at port 8080...');
 
// 监听socket连接
socket.listen(server).on('connection', function(client) {
    // 接收信息
    client.on('message', function(msg) {
        client.send('hello:' msg);
        console.log('data from client: ---> ' msg);
    });
 
    // 断开处理
    client.on('disconnect', function() {
        console.log('Client socket has closed.');
    });
});

3 赞 13 收藏 3 评论

澳门新萄京官方网站 4

1.卡塔尔(قطر‎ Cookie、LocalStorage 和 IndexDB 不能读取

        同黄金时代域名,分裂协商                不容许

2.卡塔尔 DOM 和 Js对象不可能获取

3.卡塔尔(قطر‎ AJAX 央求无法发送

           域名和域名对应相符ip              不容许

 

遍布跨域场景

           主域相近,子域差异                不许

 

U君越L                                      表明                    是还是不是允许通讯

         同风姿罗曼蒂克域名,分裂文件或路线           允许

 

         同黄金年代域名,不相同端口                不准

 

        同生龙活虎域名,分裂协商                不容许

 

           域名和域名对应相符ip              不一样意

 

           主域相仿,子域区别                不相同意

 

        不相同域名                         不准

 

        差异乡名                         不准

跨域解决方案

跨域建设方案

 

1、 通过jsonp跨域

1、 通过jsonp跨域

2、 document.domain iframe跨域

2、 document.domain iframe跨域

3、 location.hash iframe

3、 location.hash iframe

4、 window.name iframe跨域

4、 window.name iframe跨域

5、 postMessage跨域

5、 postMessage跨域

6、 跨域能源分享(CO瑞虎S)

6、 跨域能源分享(CO奇骏S)

7、 nginx代理跨域

7、 nginx代理跨域

8、 nodejs中间件代理跨域

8、 nodejs中间件代理跨域

9、 WebSocket左券跨域

9、 WebSocket商讨跨域

一、 通过jsonp跨域

 

管见所及为了减轻web服务器的载重,大家把js、css,img等静态财富抽离到另风流倜傥台独立域名的服务器上,在html页面中再经过相应的价签从区别域名下加载静态财富,而被浏览器允许,基于此原理,大家得以因而动态创建script,再恳求二个带参网站实现跨域通讯。

一、 通过jsonp跨域

1.)原生实现:

 

varscript=document.createElement('script');

事不关己为了减轻web服务器的负载,我们把js、css,img等静态能源分离到另一台独立域名的服务器上,在html页面中再通过相应的价签从不相同域名下加载静态能源,而被浏览器允许,基于此原理,我们能够透过动态创设script,再央求一个带参网址达成跨域通讯。

script.type='text/javascript';

 

// 传参并钦赐回调奉行函数为onBack

1.)原生达成:

script.src='';

 

document.head.appendChild(script);

<script>

    var script = document.createElement('script');

    script.type = 'text/javascript';

 

    // 传参并指定回调施行函数为onBack

    script.src = '';

    document.head.appendChild(script);

 

    // 回调试行函数

    function onBack(res) {

        alert(JSON.stringify(res));

    }

</script>

// 回调实行函数

 

functiononBack(res){

服务端重回如下(重临时即进行全局函数):

alert(JSON.stringify(res));

 

}

onBack({"status": true, "user": "admin"})

服务端再次来到如下(重临时即举行全局函数):

 

onBack({"status":true,"user":"admin"})

2.)jquery ajax:

2.)jquery ajax:

 

$.ajax({

$.ajax({

    url: '',

    type: 'get',

    dataType: 'jsonp',  // 央求格局为jsonp

    jsonpCallback: "onBack",    // 自定义回调函数名

    data: {}

});

url:'',

 

type:'get',

3.)vue.js:

dataType:'jsonp',// 央求格局为jsonp

 

jsonpCallback:"onBack",// 自定义回调函数名

this.$http.jsonp('', {

    params: {},

    jsonp: 'onBack'

}).then((res) => {

    console.log(res);

})

data:{}

 

});

后端node.js代码示例:

3.)vue.js:

 

this.$http.jsonp('

var querystring = require('querystring');

var http = require('http');

var server = http.createServer();

 

server.on('request', function(req, res) {

    var params = qs.parse(req.url.split('?')[1]);

    var fn = params.callback;

 

    // jsonp重回设置

    res.writeHead(200, { 'Content-Type': 'text/javascript' });

    res.write(fn   '('   JSON.stringify(params)   ')');

 

    res.end();

});

 

server.listen('8080');

console.log('Server is running at port 8080...');

params:{},

 

jsonp:'onBack'

jsonp劣点:只可以促成get一种央求。

}).then((res)=>{

 

console.log(res);

二、 document.domain iframe跨域

})

 

后端node.js代码示例:

此方案只限主域相仿,子域分化的跨域应用途景。

varquerystring=require('querystring');

 

varhttp=require('http');

兑现原理:多个页面都经过js强制设置document.domain为幼功主域,就兑现了同域。

varserver=http.createServer();

 

server.on('request',function(req,res){

1.)父窗口:()

varparams=qs.parse(req.url.split('?')[1]);

 

varfn=params.callback;

<iframe id="iframe" src=";

<script>

    document.domain = 'domain.com';

    var user = 'admin';

</script>

// jsonp再次来到设置

 

res.writeHead(200,{'Content-Type':'text/javascript'});

2.)子窗口:()

res.write(fn '(' JSON.stringify(params) ')');

 

res.end();

<script>

    document.domain = 'domain.com';

    // 获取父窗口中变量

    alert('get js data from parent ---> '   window.parent.user);

</script>

});

 

server.listen('8080');

三、 location.hash iframe跨域

console.log('Server is running at port 8080...');

 

jsonp劣势:只好兑现get大器晚成种央求。

落到实处原理: a欲与b跨域相互通讯,通过中间页c来促成。 八个页面,分歧域之间利用iframe的location.hash传值,相通域之间直接js访问来通信。

二、 document.domain iframe跨域

 

此方案只限主域相像,子域分化的跨域应用处景。

具体达成:A域:a.html -> B域:b.html -> A域:c.html,a与b不相同域只好通过hash值单向通讯,b与c也分歧域也不能不单向通讯,但c与a同域,所以c可透过parent.parent访问a页面全数目的。

兑现原理:八个页面都经过js强制设置document.domain为根基主域,就落到实处了同域。

 

1.)父窗口:()

1.)a.html:()

document.domain='domain.com';

 

varuser='admin';

<iframe id="iframe" src="" style="display:none;"></iframe>

<script>

    var iframe = document.getElementById('iframe');

 

    // 向b.html传hash值

    setTimeout(function() {

        iframe.src = iframe.src   '#user=admin';

    }, 1000);

    

    // 开放给同域c.html的回调方法

    function onCallback(res) {

        alert('data from c.html ---> '   res);

    }

</script>

2.)子窗口:()

 

document.domain='domain.com';

2.)b.html:()

// 获取父窗口中变量

 

alert('get js data from parent ---> ' window.parent.user);

<iframe id="iframe" src="" style="display:none;"></iframe>

<script>

    var iframe = document.getElementById('iframe');

 

    // 监听a.html传来的hash值,再传给c.html

    window.onhashchange = function () {

        iframe.src = iframe.src   location.hash;

    };

</script>

三、 location.hash iframe跨域

 

完毕原理: a欲与b跨域相互通讯,通过中间页c来贯彻。 两个页面,分裂域之间利用iframe的location.hash传值,相近域之间间接js访问来通讯。

3.)c.html:()

具体完结:A域:a.html -> B域:b.html -> A域:c.html,a与b区别域只好通过hash值单向通讯,b与c也区别域也只可以单向通信,但c与a同域,所以c可由此parent.parent访问a页面全数指标。

 

1.)a.html:()

<script>

    // 监听b.html传来的hash值

    window.onhashchange = function () {

        // 再经过操作同域a.html的js回调,将结果传到

        window.parent.parent.onCallback('hello: '   location.hash.replace('#user=', ''));

    };

</script>

variframe=document.getElementById('iframe');

 

// 向b.html传hash值

四、 window.name iframe跨域

setTimeout(function(){

 

iframe.src=iframe.src '#user=admin';

window.name属性的独出心裁之处:name值在分裂的页面(以至不相同域名)加载后照旧存在,而且能够支撑非常长的 name 值(2MB)。

},1000);

 

// 开放给同域c.html的回调方法

1.)a.html:()

functiononCallback(res){

 

alert('data from c.html ---> ' res);

var proxy = function(url, callback) {

    var state = 0;

    var iframe = document.createElement('iframe');

 

    // 加载跨域页面

    iframe.src = url;

 

    // onload事件会触发2次,第1次加载跨域页,并留存数据于window.name

    iframe.onload = function() {

        if (state === 1) {

            // 第2次onload(同域proxy页卡塔尔成功后,读取同域window.name中数据

            callback(iframe.contentWindow.name);

            destoryFrame();

 

        } else if (state === 0) {

            // 第1次onload(跨域页卡塔尔国成功后,切换成同域代理页面

            iframe.contentWindow.location = '';

            state = 1;

        }

    };

 

    document.body.appendChild(iframe);

 

    // 获取数据未来销毁那么些iframe,释放内部存款和储蓄器;那也保证了平安(不被别的域frame js访谈)

    function destoryFrame() {

        iframe.contentWindow.document.write('');

        iframe.contentWindow.close();

        document.body.removeChild(iframe);

    }

};

 

// 诉求跨域b页面数据

proxy('', function(data){

    alert(data);

});

}

 

2.)b.html:()

2.)proxy.html:(.

variframe=document.getElementById('iframe');

高级中学级代理页,与a.html同域,内容为空就可以。

// 监听a.html传来的hash值,再传给c.html

 

window.onhashchange=function(){

3.)b.html:()

iframe.src=iframe.src location.hash;

 

};

<script>

    window.name = 'This is domain2 data!';

</script>

3.)c.html:()

 

// 监听b.html传来的hash值

小结:通过iframe的src属性由海外转向当地方,跨域数据即由iframe的window.name从异国传递到本地点。那一个就高明地绕过了浏览器的跨域访谈节制,但同期它又是安全操作。

window.onhashchange=function(){

 

// 再通过操作同域a.html的js回调,将结果传到

五、 postMessage跨域

window.parent.parent.onCallback('hello: ' location.hash.replace('#user=',''));

 

};

postMessage是HTML5 XMLHttpRequest Level 第22中学的API,且是为数相当少能够跨域操作的window属性之生龙活虎,它可用于消除以下方面包车型客车主题素材:

四、 window.name iframe跨域

a.) 页面和其开发的新窗口的多寡传递

window.name属性的优良之处:name值在不一致的页面(以至不一致域名)加载后依旧存在,而且能够扶植相当长的 name 值(2MB)。

b.) 多窗口之间音讯传递

1.)a.html:()

c.) 页面与嵌套的iframe音信传递

varproxy=function(url,callback){

d.) 上面四个现象的跨域数据传递

varstate=0;

 

variframe=document.createElement('iframe');

用法:postMessage(data,origin卡塔尔(قطر‎方法采用三个参数

// 加载跨域页面

data: html5行业内部扶助放肆基本项目或可复制的对象,但局地浏览器只扶植字符串,所以传参时最佳用JSON.stringify(卡塔尔(قطر‎体系化。

iframe.src=url;

origin: 左券 主机 端口号,也能够设置为”*”,表示能够传递给自由窗口,假如要钦定和当前窗口同源的话设置为”/”。

// onload事件会触发2次,第1次加载跨域页,并设有数据于window.name

 

iframe.onload=function(){

1.)a.html:()

if(state===1){

 

// 第2次onload(同域proxy页卡塔尔成功后,读取同域window.name中数量

<iframe id="iframe" src="" style="display:none;"></iframe>

<script>      

    var iframe = document.getElementById('iframe');

    iframe.onload = function() {

        var data = {

            name: 'aym'

        };

        // 向domain2传送跨域数据

        iframe.contentWindow.postMessage(JSON.stringify(data), '');

    };

 

    // 选取domain2再次回到数据

    window.addEventListener('message', function(e) {

        alert('data from domain2 ---> '   e.data);

    }, false);

</script>

callback(iframe.contentWindow.name);

 

destoryFrame();

2.)b.html:()

}elseif(state===0){

 

// 第1次onload(跨域页卡塔尔国成功后,切换成同域代理页面

<script>

    // 接收domain1的数据

    window.addEventListener('message', function(e) {

        alert('data from domain1 ---> '   e.data);

 

        var data = JSON.parse(e.data);

        if (data) {

            data.number = 16;

 

            // 管理后再发回domain1

            window.parent.postMessage(JSON.stringify(data), '');

        }

    }, false);

</script>

iframe.contentWindow.location='';

 

state=1;

六、 跨域财富分享(CO奥迪Q7S)

}

 

};

普通跨域央浼:只服务端设置Access-Control-Allow-Origin就能够,前端无须设置。

document.body.appendChild(iframe);

带cookie乞请:前后端都亟需设置字段,此外部要求注意:所带cookie为跨域央求接口所在域的cookie,而非当前页。

// 获取数据未来销毁这几个iframe,释放内部存款和储蓄器;那也确认保证了金昌(不被此外域frame js访谈)

近来,全体浏览器都协理该作用(IE8 :IE8/9内需接收XDomainRequest对象来支撑CORubiconS)卡塔尔(英语:State of Qatar),CO奥迪Q7S也早已成为主流的跨域实施方案。

functiondestoryFrame(){

 

iframe.contentWindow.document.write('');

1、 前端设置:

iframe.contentWindow.close();

 

document.body.removeChild(iframe);

1.)原生ajax

}

 

};

// 前端安装是还是不是带cookie

xhr.withCredentials = true;

// 央求跨域b页面数据

 

proxy('

示范代码:

alert(data);

 

});

var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容

 

// 前端安装是还是不是带cookie

xhr.withCredentials = true;

 

xhr.open('post', '', true);

xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

xhr.send('user=admin');

 

xhr.onreadystatechange = function() {

    if (xhr.readyState == 4 && xhr.status == 200) {

        alert(xhr.responseText);

    }

};

2.)proxy.html:(.

 

中级代理页,与a.html同域,内容为空就能够。

2.)jQuery ajax

3.)b.html:()

 

window.name='This is domain2 data!';

$.ajax({

    ...

   xhrFields: {

       withCredentials: true    // 前端安装是不是带cookie

   },

   crossDomain: true,   // 会让恳求头中蕴藏跨域的附加新闻,但不会含cookie

    ...

});

计算:通过iframe的src属性由海外转向当地点,跨域数据即由iframe的window.name从异国传递到本地点。这么些就高明地绕过了浏览器的跨域访谈节制,但还要它又是安全操作。

 

五、 postMessage跨域

3.)vue框架

postMessage是HTML5 XMLHttpRequest Level 第22中学的API,且是微量能够跨域操作的window属性之大器晚成,它可用以缓慢解决以下地方的主题材料:

 

a.) 页面和其开发的新窗口的数量传递

在vue-resource封装的ajax组件中出席以下代码:

b.) 多窗口之间音讯传递

 

c.) 页面与嵌套的iframe新闻传递

Vue.http.options.credentials = true

d.) 上边七个场景的跨域数据传递

 

用法:postMessage(data,origin卡塔尔(英语:State of Qatar)方法选用多少个参数

2、 服务端设置:

data: html5专门的学问辅助放肆基本项目或可复制的对象,但局地浏览器只扶持字符串,所以传参时最棒用JSON.stringify(卡塔尔国系列化。

 

origin: 公约 主机 端口号,也足以设置为”*”,表示能够传递给自由窗口,假若要钦命和当前窗口同源的话设置为”/”。

若后端设置成功,前端浏览器调节台则不会情不自禁跨域报错新闻,反之,表明没设成功。

1.)a.html:()

 

variframe=document.getElementById('iframe');

1.)Java后台:

iframe.onload=function(){

 

vardata={

/*

* 导入包:import javax.servlet.http.HttpServletResponse;

* 接口参数中定义:HttpServletResponse response

*/

response.setHeader("Access-Control-Allow-Origin", ""卡塔尔(قطر‎;  // 若有端口需写全(左券 域名 端口)

response.setHeader("Access-Control-Allow-Credentials", "true");

name:'aym'

 

};

2.)Nodejs后台示例:

// 向domain2传送跨域数据

 

iframe.contentWindow.postMessage(JSON.stringify(data),'');

var http = require('http');

var server = http.createServer();

var qs = require('querystring');

 

server.on('request', function(req, res) {

    var postData = '';

 

    // 数据块选用中

    req.addListener('data', function(chunk) {

        postData  = chunk;

    });

 

    // 数据采用达成

    req.addListener('end', function() {

        postData = qs.parse(postData);

 

        // 跨域后台装置

        res.writeHead(200, {

            'Access-Control-Allow-Credentials': 'true',     // 后端允许发送Cookie

            'Access-Control-Allow-Origin': '',    // 允许访问的域(合同 域名 端口)

            'Set-Cookie': 'l=a123456;帕特h=/;Domain=www.domain2.com;HttpOnly'   // HttpOnly:脚本不能够读取cookie

        });

 

        res.write(JSON.stringify(postData));

        res.end();

    });

});

 

server.listen('8080');

console.log('Server is running at port 8080...');

};

 

// 接受domain2再次来到数据

七、 nginx代理跨域

window.addEventListener('message',function(e){

 

alert('data from domain2 ---> ' e.data);

1、 nginx配置消除iconfont跨域

},false);

 

2.)b.html:()

浏览器跨域访问js、css、img等常规静态能源被同源攻略获准,但iconfont字体文件(eot|otf|ttf|woff|svg卡塔尔(英语:State of Qatar)例外,这时可在nginx的静态财富服务器中到场以下配置。

// 接收domain1的数据

 

window.addEventListener('message',function(e){

location / {

  add_header Access-Control-Allow-Origin *;

}

alert('data from domain1 ---> ' e.data);

 

vardata=JSON.parse(e.data);

2、 nginx反向代理接口跨域

if(data){

 

data.number=16;

跨域原理: 同源战术是浏览器的安全战略,不是HTTP合同的风姿罗曼蒂克有些。服务器端调用HTTP接口只是利用HTTP左券,不会实施JS脚本,无需同源计谋,也就不设有超出难点。

// 管理后再发回domain1

 

window.parent.postMessage(JSON.stringify(data),'');

兑现思路:通过nginx配置二个代理服务器(域名与domain1雷同,端口差异)做跳板机,反向代理访谈domain2接口,况且能够顺便改良cookie中domain消息,方便当前域cookie写入,实现跨域登陆。

}

 

},false);

nginx具体安插:

六、 跨域能源共享(CO奥迪Q5S)

 

日常来讲跨域央求:只服务端设置Access-Control-Allow-Origin就可以,前端无须设置。

#proxy服务器

server {

    listen       81;

    server_name  www.domain1.com;

 

    location / {

        proxy_pass   ;  #反向代理

        proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie里域名

        index  index.html index.htm;

 

        # 当用webpack-dev-server等中间件代理接口访谈nignx时,那时无浏览器参与,故并未有同源节制,上边包车型地铁跨域配置可不启用

        add_header Access-Control-Allow-Origin ;  #脚下端只跨域不带cookie时,可为*

        add_header Access-Control-Allow-Credentials true;

    }

}

带cookie央浼:前后端都亟需设置字段,其它部供给注意:所带cookie为跨域诉求接口所在域的cookie,而非当前页。

 

脚下,全体浏览器都协理该意义(IE8 :IE8/9急需动用XDomainRequest对象来帮衬CO奥迪Q5S)卡塔尔,CO凯雷德S也已经改为主流的跨域建设方案。

1.卡塔尔(英语:State of Qatar)前端代码示例:

1、 前端设置:

 

1.)原生ajax

var xhr = new XMLHttpRequest();

 

// 前端开关:浏览器是否读写cookie

xhr.withCredentials = true;

 

// 访问nginx中的代理服务器

xhr.open('get', '', true);

xhr.send();

// 前端安装是不是带cookie

 

xhr.withCredentials=true;

2.卡塔尔(قطر‎ Nodejs后台示例:

示范代码:

 

varxhr=newXMLHttpRequest();// IE8/9需用window.XDomainRequest兼容

var http = require('http');

var server = http.createServer();

var qs = require('querystring');

 

server.on('request', function(req, res) {

    var params = qs.parse(req.url.substring(2));

 

    // 向前台写cookie

    res.writeHead(200, {

        'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly'   // HttpOnly:脚本不可能读取

    });

 

    res.write(JSON.stringify(params));

    res.end();

});

 

server.listen('8080');

console.log('Server is running at port 8080...');

// 前端安装是或不是带cookie

 

xhr.withCredentials=true;

八、 Nodejs中间件代理跨域

xhr.open('post',');

 

xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');

node中间件完成跨域代理,原理大约与nginx相同,都是由此启多个代理服务器,达成数量的转变。

xhr.send('user=admin');

 

xhr.onreadystatechange=function(){

1、 非vue框架的跨域(2次跨域)

if(xhr.readyState==4&&xhr.status==200){

 

alert(xhr.responseText);

应用node express http-proxy-middleware搭建叁个proxy服务器。

}

 

};

1.)前端代码示例:

2.)jQuery ajax

 

$.ajax({

var xhr = new XMLHttpRequest();

 

// 前端按键:浏览器是或不是读写cookie

xhr.withCredentials = true;

 

// 采访http-proxy-middleware代理服务器

xhr.open('get', '', true);

xhr.send();

...

 

xhrFields:{

2.)中间件服务器:

withCredentials:true// 前端安装是或不是带cookie

 

},

var express = require('express');

var proxy = require('http-proxy-middleware');

var app = express();

 

app.use('/', proxy({

    // 代理跨域指标接口

    target: '',

    changeOrigin: true,

 

    // 纠正响应头音讯,实现跨域并允许带cookie

    onProxyRes: function(proxyRes, req, res) {

        res.header('Access-Control-Allow-Origin', '');

        res.header('Access-Control-Allow-Credentials', 'true');

    },

 

    // 修改响应音信中的cookie域名

    cookieDomainRewrite: 'www.domain1.com'  // 可感到false,表示不订正

}));

 

app.listen(3000);

console.log('Proxy server is listen at port 3000...');

crossDomain:true,// 会让央求头中蕴藏跨域的附加音讯,但不会含cookie

 

...

3.)Nodejs后台同(六:nginx)

});

 

3.)vue框架

2、 vue框架的跨域(1次跨域)

在vue-resource封装的ajax组件中参加以下代码:

 

Vue.http.options.credentials = true

行使node webpack webpack-dev-server代理接口跨域。在开垦条件下,由于vue渲染服务和接口代理服务都以webpack-dev-server同三个,所以页面与代理接口之间不再跨域,无须设置headers跨域新闻了。

2、 服务端设置:

 

若后端设置成功,前端浏览器调控台则不晤面世跨域报错音信,反之,表达没设成功。

webpack.config.js部分配置:

1.)Java后台:

 

/*

module.exports = {

    entry: {},

    module: {},

    ...

    devServer: {

        historyApiFallback: true,

        proxy: [{

            context: '/login',

            target: '',  // 代理跨域指标接口

            changeOrigin: true,

            cookieDomainRewrite: 'www.domain1.com'  // 可认为false,表示不改动

        }],

        noInfo: true

    }

}

* 导入包:import javax.servlet.http.HttpServletResponse;

 

* 接口参数中定义:HttpServletResponse response

九、 WebSocket协商跨域

*/

 

response.setHeader("Access-Control-Allow-Origin"," 若有端口需写全(合同 域名 端口)

WebSocket protocol是HTML5风度翩翩种新的情商。它完结了浏览器与服务器全双工通讯,同期允许跨域通讯,是server push技能的风姿罗曼蒂克种很好的兑现。

response.setHeader("Access-Control-Allow-Credentials","true");

原生WebSocket API使用起来不太有利,大家使用Socket.io,它很好地卷入了webSocket接口,提供了更简约、灵活的接口,也对不援助webSocket的浏览器提供了向下包容。

2.)Nodejs后台示例:

 

varhttp=require('http');

1.)前端代码:

varserver=http.createServer();

 

varqs=require('querystring');

<div>user input:<input type="text"></div>

<script src="./socket.io.js"></script>

<script>

var socket = io('');

 

// 连接成功拍卖

socket.on('connect', function() {

    // 监听服务端音讯

    socket.on('message', function(msg) {

        console.log('data from server: ---> '   msg);

    });

 

    // 监听服务端关闭

    socket.on('disconnect', function() {

        console.log('Server socket has closed.');

    });

});

 

document.getElementsByTagName('input')[0].onblur = function() {

    socket.send(this.value);

};

</script>

server.on('request',function(req,res){

 

varpostData='';

2.)Nodejs socket后台:

// 数据块选用中

 

req.addListener('data',function(chunk){

var http = require('http');

var socket = require('socket.io');

 

// 启http服务

var server = http.createServer(function(req, res) {

    res.writeHead(200, {

        'Content-type': 'text/html'

    });

    res.end();

});

 

server.listen('8080');

console.log('Server is running at port 8080...');

 

// 监听socket连接

socket.listen(server).on('connection', function(client) {

    // 采取音讯

    client.on('message', function(msg) {

        client.send('hello:'   msg);

        console.log('data from client: ---> '   msg);

    });

 

    // 断开管理

    client.on('disconnect', function() {

        console.log('Client socket has closed.');

    });

});

postData =chunk;

 

});

转自:

// 数据选用实现

req.addListener('end',function(){

postData=qs.parse(postData);

// 跨域后台装置

res.writeHead(200,{

'Access-Control-Allow-Credentials':'true',// 后端允许发送Cookie

'Access-Control-Allow-Origin':' 允许访谈的域(公约 域名 端口)

'Set-Cookie':'l=a123456;帕特h=/;Domain=www.domain2.com;HttpOnly'// HttpOnly:脚本不可能读取cookie

});

res.write(JSON.stringify(postData));

res.end();

});

});

server.listen('8080');

console.log('Server is running at port 8080...');

七、 nginx代理跨域

1、 nginx配置化解iconfont跨域

浏览器跨域访谈js、css、img等常规静态能源被同源战术批准,但iconfont字体文件(eot|otf|ttf|woff|svg卡塔尔(قطر‎例外,那时可在nginx的静态财富服务器中参预以下配置。

location/{

add_headerAccess-Control-Allow-Origin *;

}

2、 nginx反向代理接口跨域

跨域原理: 同源计谋是浏览器的安全计谋,不是HTTP左券的大器晚成部分。服务器端调用HTTP接口只是利用HTTP公约,不会实施JS脚本,没有必要同源计谋,也就海市蜃楼超越问题。

落到实处思路:通过nginx配置五个代理服务器(域名与domain1相仿,端口分化)做跳板机,反向代理访问domain2接口,而且能够顺便更正cookie中domain音信,方便当前域cookie写入,完成跨域登入。

nginx具体铺排:

#proxy服务器

server{

listen81;

server_namewww.domain1.com;

location/{

proxy_pass;  #反向代理

proxy_cookie_domainwww.domain2.comwww.domain1.com;#修改cookie里域名

indexindex.htmlindex.htm;

# 当用webpack-dev-server等中间件代理接口访谈nignx时,那时候无浏览器参与,故并未有同源约束,下边包车型大巴跨域配置可不启用

add_headerAccess-Control-Allow-Origin;  #眼前端只跨域不带cookie时,可为*

add_headerAccess-Control-Allow-Credentialstrue;

}

}

1.卡塔尔(英语:State of Qatar)前端代码示例:

varxhr=newXMLHttpRequest();

// 前端按钮:浏览器是或不是读写cookie

xhr.withCredentials=true;

// 访谈nginx中的代理服务器

xhr.open('get',');

xhr.send();

2.卡塔尔(قطر‎ Nodejs后台示例:

varhttp=require('http');

varserver=http.createServer();

varqs=require('querystring');

server.on('request',function(req,res){

varparams=qs.parse(req.url.substring(2));

// 向前台写cookie

res.writeHead(200,{

'Set-Cookie':'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly'// HttpOnly:脚本不恐怕读取

});

res.write(JSON.stringify(params));

res.end();

});

server.listen('8080');

console.log('Server is running at port 8080...');

八、 Nodejs中间件代理跨域

node中间件达成跨域代理,原理大致与nginx雷同,都以透过启一个代理服务器,达成多少的转账。

1、 非vue框架的跨域(2次跨域)

使用node express http-proxy-middleware搭建二个proxy服务器。

1.)前端代码示例:

varxhr=newXMLHttpRequest();

// 前端开关:浏览器是不是读写cookie

xhr.withCredentials=true;

// 访问http-proxy-middleware代理服务器

xhr.open('get',');

xhr.send();

2.)中间件服务器:

varexpress=require('express');

varproxy=require('http-proxy-middleware');

varapp=express();

app.use('/',proxy({

// 代理跨域指标接口

target:'',

changeOrigin:true,

// 改善响应头新闻,达成跨域并允许带cookie

onProxyRes:function(proxyRes,req,res){

res.header('Access-Control-Allow-Origin','');

res.header('Access-Control-Allow-Credentials','true');

},

// 改正响应新闻中的cookie域名

cookieDomainRewrite:'www.domain1.com'// 可感觉false,表示不退换

}));

app.listen(3000);

console.log('Proxy server is listen at port 3000...');

3.)Nodejs后台同(六:nginx)

2、 vue框架的跨域(1次跨域)

应用node webpack webpack-dev-server代理接口跨域。在开垦意况下,由于vue渲染服务和接口代理服务都是webpack-dev-server同几个,所以页面与代理接口之间不再跨域,无须设置headers跨域消息了。

webpack.config.js部分配置:

module.exports={

entry:{},

module:{},

...

devServer:{

historyApiFallback:true,

proxy:[{

context:'/login',

target:' 代理跨域指标接口

changeOrigin:true,

cookieDomainRewrite:'www.domain1.com'// 可认为false,表示不变

}],

noInfo:true

}

}

九、 WebSocket研讨跨域

WebSocket protocol是HTML5风度翩翩种新的磋商。它完毕了浏览器与服务器全双工通讯,同临时候同意跨域通信,是server push手艺的生机勃勃种很好的落到实处。

原生WebSocket API使用起来不太有利,大家采取Socket.io,它很好地卷入了webSocket接口,提供了更简明、灵活的接口,也对不支持webSocket的浏览器提供了向下宽容。

1.)前端代码:

userinput:

varsocket=io('');

// 连接成功拍卖

socket.on('connect',function(){

// 监听服务端音讯

socket.on('message',function(msg){

console.log('data from server: ---> ' msg);

});

// 监听服务端关闭

socket.on('disconnect',function(){

console.log('Server socket has closed.');

});

});

document.getElementsByTagName('input')[0].onblur=function(){

socket.send(this.value);

};

2.)Nodejs socket后台:

varhttp=require('http');

varsocket=require('socket.io');

// 启http服务

varserver=http.createServer(function(req,res){

res.writeHead(200,{

'Content-type':'text/html'

});

res.end();

});

server.listen('8080');

console.log('Server is running at port 8080...');

// 监听socket连接

socket.listen(server).on('connection',function(client){

// 选择消息

client.on('message',function(msg){

client.send('hello:' msg);

console.log('data from client: ---> ' msg);

});

// 断开管理

client.on('disconnect',function(){

console.log('Client socket has closed.');

});

});

本文由澳门新萄京官方网站发布于澳门新萄京赌场网址,转载请注明出处:澳门新萄京官方网站:焚林而猎跨域的方案,不

关键词: