澳门新浦京娱乐场网站-www.146.net-新浦京娱乐场官网
做最好的网站

澳门新浦京娱乐场网站:前端常见跨域解决方案

并不是再问笔者跨域的难题了

2018/07/16 · 基础手艺 · 跨域

初藳出处: 写Bug   

写下那篇小说后作者想,要否则后就把这种基础的大范围知识都归到这几个“不要再问小编XX的标题”,形成黄金年代多元内容,希望咱们看完事后再有人问您这个主题素材,你内心会窃喜:“嘿嘿,是时候表现真正的能力了!”
一、实际不是再问笔者this的指向难点了

跨域这多少个字就如一块狗皮膏药同样黏在每叁个前端开荒者身上,无论你在办事上还是面试中无可防止会遇见那么些难题。为了应景面试,作者每一次都不管背多少个方案,也不驾驭怎么要这么干,反正面完就可以扔了,笔者想做事上也不会用到那么多混淆黑白的方案。到了确实行事,开拓条件有webpack-dev-server解决,上线了服务端的大佬们也会配好,配了如何自身不管,反正不会跨域便是了。日子也就那样混过去了,终于有一天,作者感觉无法再持续这么混下去了,作者自然要根本搞懂这些事物!于是就有了那篇小说。

前面一个常见跨域应用方案(全)

2017/09/14 · 基础本领 · 3 评论 · 跨域

初藳出处: 安静de沉淀   

什么是跨域?

何以是跨域?

要调整跨域,首先要了然为何会有跨域那些难点应时而生

真正,我们这种搬砖工人正是为了混口饭吃嘛,好好的调个接口告诉本人跨域了,这种阻碍大家轻易搬砖的政工真恶心!为何会跨域?是何人在搞专业?为了找到那个标题标罪魁祸首,请点击浏览器的同源战术。
这么官方的东西真难懂,没涉及,最少你理解了,因为浏览器的同源战术导致了跨域,就是浏览器在搞专业。
由此,浏览器为啥要搞职业?便是不想给好日子大家过?对于这么的狐疑,浏览器甩锅道:“同源计策节制了从同二个源加载的文书档案或脚本怎么样与来自另二个源的财富开展交互。那是一个用来隔断潜在恶意文件的要害安全部制。”
那样官方的话术真难懂,没提到,起码你知道了,好似那是个平平安安体制。
据此,究竟为何需求那样的平安机制?那样的平安机制消释了如何难点?别急,让我们一而再再而三研讨下去。

什么是跨域?

跨域是指一个域下的文书档案或脚本盘算去乞请另八个域下的财富,这里跨域是广义的。

广义的跨域:

1.) 财富跳转: A链接、重定向、表单提交 2.) 财富嵌入:<link>、<script>、<img>、<frame>等dom标签,还会有样式中background:url()、@font-face()等公事外链 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(Same origin policy)是生机勃勃种约定,由Netscape公司一九九四年引进浏览器,它是浏览器最基本也最中烟酸心得安全功用,如若紧缺了同源攻略,浏览器超轻松受到XSS、CSFSportage等攻击。所谓同源是指”合同 域名 端口”三者风流浪漫致,就算五个不等的域名指向同贰个ip地址,也非同源。

同源战术限定之下二种行为:

1.) 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大切诺基L 表明 是还是不是允许通讯 同风度翩翩域名,不相同文件或路线 允许 同意气风发域名,差异端口 不容许 同意气风发域名,分歧协商 不容许 域名和域名对应相仿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中”,那样一来,这几个不French Open站就一定于登入了您的账号,可认为所欲为了!尽管那不是二个买买买账号,而是你的银行账号,那……
那正是风传中的CSCR-VF攻击浅谈CSRubiconF攻击格局。
看了那波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、 跨域能源共享(COWranglerS)
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') 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'); script.type = 'text/javascript'; // 传参并钦定回调执行函数为onBack script.src = ''; document.head.appendChild(script); // 回调推行函数 function onBack(res) { alert(JSON.stringify(res)); } </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: {} });

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]); 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...');

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); </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公司1992年引进浏览器,它是浏览器最大旨也最中央的安全作用,要是缺点和失误了同源攻略,浏览器十分轻松境遇XSS、CSF奥迪Q5等攻击。所谓同源是指”契约 域名 端口”三者生机勃勃致,固然两个不等的域名指向同二个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') // 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 克罗斯Domain { 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.add伊芙ntListener('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

COEvoqueS是一个W3C标准,全称是”跨域能源分享”(Cross-origin resource sharing)跨域能源共享 CORAV4S 详解。看名字就驾驭那是拍卖跨域难题的正式做法。CO福睿斯S有三种央浼,轻巧伏乞和非简单伏乞。

这里援引上边链接阮风度翩翩峰先生的篇章证实一下总结央浼和非轻松诉求。
浏览器将COXC60S必要分成两类:轻巧央求(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) // 非差不离需要的COENVISIONS央浼,会在专门的学问通讯早前,扩张贰遍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才是更通用的做法吧。

三、 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() 是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.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,toDataUPRADOL跨域难题

四、 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(); } 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); });

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()等公事外链

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() { var data = { name: 'aym' }; // 向domain2传送跨域数据 iframe.contentWindow.postMessage(JSON.stringify(data), ''); }; // 接纳domain2重返数据 window.add伊芙ntListener('message', function(e) { alert('data from domain2 ---> ' e.data); }, 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.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>

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对象不恐怕获得

六、 跨域财富分享(COHavalS)

平凡跨域央浼:只服务端设置Access-Control-Allow-Origin就可以,前端无须设置。
带cookie央求:前后端都亟需设置字段,其余部要求注意:所带cookie为跨域伏乞接口所在域的cookie,而非当前页。
当前,全体浏览器都协理该意义(IE8 :IE8/9亟待动用XDomainRequest对象来支撑CO哈弗S)),CO奔驰G级S也已经济体改为主流的跨域施工方案。

 

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 ... });

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'); 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;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...');

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...');

 

U猎豹CS6L表达是或不是允许通讯

七、 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.) 前端代码示例:

var xhr = new XMLHttpRequest(); // 前端开关:浏览器是或不是读写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)); // 向前台写cookie res.writeHead(200, { 'Set-Cookie': 'l=a123456;帕特h=/;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(萨姆e origin policy)是生机勃勃种约定,由Netscape集团1994年引入浏览器,它是浏览器最主题也最主题的武威成效,假如缺少了同源战略,浏览器相当轻巧受到XSS、CSF陆风X8等攻击。所谓同源是指”合同 域名 端口”三者大器晚成致,即便四个不等的域名指向同三个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...');

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) { 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>

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) { // 接纳新闻 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.'); }); });

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.) 库克ie、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、 跨域财富分享(COEvoqueS)

6、 跨域财富分享(CO福特ExplorerS)

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马自达MX-5S)

}

 

};

平常来讲跨域诉求:只服务端设置Access-Control-Allow-Origin就能够,前端无须设置。

document.body.appendChild(iframe);

带cookie需要:前后端都急需安装字段,此外部须求注意:所带cookie为跨域央求接口所在域的cookie,而非当前页。

// 获取数据今后销毁那一个iframe,释放内部存款和储蓄器;那也确认保障了海东(不被其余域frame js访谈)

当下,全数浏览器都接济该功用(IE8 :IE8/9急需运用XDomainRequest对象来帮忙CO帕杰罗S)),COWranglerS也曾经济体改为主流的跨域设计方案。

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)方法选择八个参数

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;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...');

};

 

// 选用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)例外,那时可在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具体安顿:

六、 跨域财富共享(COPRADOS)

 

平日跨域诉求:只服务端设置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对象来扶助COCRUISERS)),CO帕杰罗S也早已改为主流的跨域应用方案。

1.)前端代码示例:

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;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...');

七、 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.)前端代码示例:

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.');

});

});

本文由澳门新浦京娱乐场网站发布于新浦京娱乐场官网,转载请注明出处:澳门新浦京娱乐场网站:前端常见跨域解决方案