跨域财富分享 COMuranoS

因为是眼下主流的跨域化解方案。所以那边多介绍点。
简介

COWranglerS是一个W3C标准,全称是”跨域能源分享”(Cross-origin resource
sharing)。
它同意浏览器向跨源服务器,发出XMLHttpRequest诉求,进而制服了AJAX只好同源使用的限定。

CO汉兰达S要求浏览器和服务器同一时候援助。近些日子,全体浏览器都帮助该意义,IE浏览器不能低于IE10。IE8+:IE8/9亟需运用XDomainRequest对象来支撑COOdysseyS。

全体CORubiconS通讯进度,都以浏览器自动完结,不要求用户参加。对于开辟者来讲,CO普拉多S通讯与同源的AJAX通讯没有差距,代码完全等同。浏览器一旦发觉AJAX央浼跨源,就能够活动抬高级中学一年级些附加的头音讯,一时还有大概会多出二回附加的乞求,但用户不会有以为。
因而,实现COOdysseyS通信的最首借使服务器。只要服务器完毕了CO中华VS接口,就足以跨源通讯。
二种乞求

谈到来很搞笑,分为二种央求,一种是简特邀求,另一种是非简单哀告。只要满意上面条件正是粗略央求

恳请方式为HEAD、POST 或然 GET
http头信息不超过一下字段:Accept、Accept-Language 、 Content-Language、
Last-伊芙nt-ID、
Content-Type(限于四个值:application/x-www-form-urlencoded、multipart/form-data、text/plain)

为什么要分成轻巧央浼和非轻易乞请,因为浏览器对这两种诉求方式的处理情势是分歧的。
简单的讲哀告
着力流程

对此简易伏乞,浏览器直接爆发COEscortS诉求。具体来讲,便是在头新闻之中,扩展一个Origin字段。
下边是二个例子,浏览器开掘此番跨源AJAX央求是简单哀告,就活动在头信息之中,增多三个Origin字段。

JavaScript

GET /cors HTTP/1.1 Origin: Host: api.alice.com
Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0

1
2
3
4
5
6
7
GET /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0

Origin字段用来评释,此次供给来自哪个源(协议 + 域名 +
端口)。服务器根据那些值,决定是或不是同意此次央求。

假定Origin钦命的源,不在许可限制内,服务器会回到贰个符合规律化的HTTP回应。
浏览器发掘,那几个回答的头音信尚未包括Access-Control-Allow-Origin字段(详见下文),就清楚出错了,进而抛出八个错误,被XMLHttpRequest的onerror回调函数捕获。

在意,这种不当不也许通过境况码识别,因为HTTP回应的状态码有相当大也许是200。

设若Origin钦赐的域名在批准范围内,服务器再次回到的响应,会多出多少个头音信字段。

JavaScript

Access-Control-Allow-Origin:
Access-Control-Allow-Credentials: true Access-Control-Expose-Headers:
FooBar Content-Type: text/html; charset=utf-8

1
2
3
4
   Access-Control-Allow-Origin: http://api.bob.com
   Access-Control-Allow-Credentials: true
   Access-Control-Expose-Headers: FooBar
   Content-Type: text/html; charset=utf-8

澳门凯旋门注册网址,上边的头消息之中,有多少个与COSportageS央浼相关的字段,都是Access-Control-早先

  • Access-Control-Allow-Origin
    :该字段是必须的。它的值要么是伸手时Origin字段的值,要么是三个*,表示接受放肆域名的央求
  • 凯旋门074网址,Access-Control-Allow-Credentials:
    该字段可选。它的值是叁个布尔值,表示是或不是允许发送Cookie。私下认可情状下,Cookie不包含在COEvoqueS诉求之中。设为true,即表示服务器明显批准,Cookie能够分包在伸手中,一齐发给服务器。那个值也只可以设为true,借使服务器不要浏览器发送Cookie,删除该字段就能够。
  • Access-Control-Expose-Headers:该字段可选。COPRADOS央求时,XMLHttpRequest对象的getResponseHeader()方法只好得到6个宗旨字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如若想获得其余字段,就务须在Access-Control-Expose-Headers里面钦命。

withCredentials 属性

下边聊起,CO索罗德S央求暗中同意不发送Cookie和HTTP认证消息。就算要把Cookie发到服务器,一方面要服务器同意,内定Access-Control-Allow-Credentials字段。

一边,开荒者必须在AJAX央浼中张开withCredentials属性。

JavaScript

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); } }; // jquery $.ajax({
… xhr菲尔德s: { withCredentials: true // 前端安装是或不是带cookie },
crossDomain: true, // 会让伏乞头中包蕴跨域的额外音讯,但不会含cookie …
});

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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);
    }
};
 
// jquery
$.ajax({
    …
   xhrFields: {
       withCredentials: true    // 前端设置是否带cookie
   },
   crossDomain: true,   // 会让请求头中包含跨域的额外信息,但不会含cookie
    …
});

不然,纵然服务器同意发送Cookie,浏览器也不会发送。只怕,服务器要求安装Cookie,浏览器也不会管理。
可是,假诺省略withCredentials设置,有的浏览器依旧会共同发送Cookie。那时,能够显式关闭withCredentials。

急需当心的是,假诺要发送Cookie,Access-Control-Allow-Origin就无法设为星号,必须内定显著的、与央浼网页一致的域名。同一时间,Cookie依然依照同源政策,唯有用服务器域名设置的Cookie才会上传,其余域名的Cookie并不会上传,且(跨源)原网页代码中的document.cookie也心有余而力不足读取服务器域名下的库克ie。
非简单央求

非轻便乞请是这种对服务器有特殊需要的央浼,比方哀告方法是PUT或DELETE,或然Content-Type字段的门类是application/json。

非轻巧乞请的CO奥迪Q3S须要,会在正式通讯在此之前,增添三遍HTTP查询央求,称为”预检”须要(preflight)。

浏览器先通晓服务器,当前网页所在的域名是不是在服务器的许可名单之中,以及能够使用什么HTTP动词和头音信字段。唯有获得一定答应,浏览器才会时有发生正式的XMLHttpRequest伏乞,否则就报错。

JavaScript

var url = ”; var xhr = new XMLHttpRequest();
xhr.open(‘PUT’, url, true); xhr.setRequestHeader(‘X-Custom-Header’,
‘value’); xhr.send();

1
2
3
4
5
var url = ‘http://api.alice.com/cors’;
var xhr = new XMLHttpRequest();
xhr.open(‘PUT’, url, true);
xhr.setRequestHeader(‘X-Custom-Header’, ‘value’);
xhr.send();

浏览器开采,那是叁个非简单央求,就自行发出三个”预检”乞求,供给服务器确认能够那样诉求。上边是其一”预检”伏乞的HTTP头音讯。

JavaScript

OPTIONS /cors HTTP/1.1 Origin:
Access-Control-Request-Method: PUT Access-Control-Request-Headers:
X-Custom-Header Host: api.alice.com Accept-Language: en-US Connection:
keep-alive User-Agent: Mozilla/5.0…

1
2
3
4
5
6
7
8
    OPTIONS /cors HTTP/1.1
   Origin: http://api.bob.com
   Access-Control-Request-Method: PUT
   Access-Control-Request-Headers: X-Custom-Header
   Host: api.alice.com
   Accept-Language: en-US
   Connection: keep-alive
   User-Agent: Mozilla/5.0…

“预检”央浼用的央求方法是OPTIONS,表示那几个乞请是用来询问的。头音讯里面,关键字段是Origin,表示央求来自哪个源。

除此之外Origin字段,”预检”央求的头消息富含七个例外字段。

Access-Control-Request-Method:该字段是必须的,用来列出浏览器的CO奔驰M级S央求会用到什么HTTP方法,上例是PUT。
Access-Control-Request-Headers:该字段是二个逗号分隔的字符串,钦点浏览器CO逍客S央浼会附加发送的头新闻字段,上例是X-Custom-Header

预检央浼的答疑

服务器收到”预检”央求未来,检查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段未来,确认允许跨源央求,就足以做出回答

JavaScript

HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 01:15:39 GMT Server:
Apache/2.0.61 (Unix) Access-Control-Allow-Origin:
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header Content-Type: text/html;
charset=utf-8 Content-Encoding: gzip Content-Length: 0 Keep-Alive:
timeout=2, max=100 Connection: Keep-Alive Content-Type: text/plain

1
2
3
4
5
6
7
8
9
10
11
12
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain

上边的HTTP回应中,关键的是Access-Control-Allow-Origin字段,表示

假若浏览器否定了”预检”诉求,会重临三个平常化的HTTP回应,不过从未其余COLX570S相关的头音讯字段。那时,浏览器就能断定,服务器不允许预检须求,由此触发贰个谬误,被XMLHttpRequest对象的onerror回调函数捕获。调控台会打字与印刷出如下的报错音信。

服务器回应的其他CO途乐S相关字段如下:

JavaScript

Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Allow-Credentials: true Access-Control-Max-Age: 1728000

1
2
3
4
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 1728000
  • Access-Control-Allow-Methods:该字段必需,它的值是逗号分隔的贰个字符串,注明服务器帮衬的所有跨域要求的格局。注意,再次回到的是有所协助的方法,而不单是浏览器乞请的百般方式。那是为着幸免频仍”预检”央求。
  • Access-Control-Allow-Headers:要是浏览器乞请包涵Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是至关重要的。它也是一个逗号分隔的字符串,注明服务器帮助的兼具头音讯字段,不制止浏览器在”预检”中呼吁的字段。
  • Access-Control-Allow-Credentials: 该字段与简短央求时的意思同样。
  • Access-Control-马克斯-Age:
    该字段可选,用来钦定本次预检须要的有效期,单位为秒。下面结果中,保质期是20天(172九千秒),即允许缓存该条回应172九千秒(即20天),在此期间,不用发出另一条预检伏乞。

浏览器日常哀求应对

假设服务器通过了”预检”央浼,今后每回浏览器平常的COEvoqueS乞求,就都跟轻巧乞请一样,会有一个Origin头新闻字段。服务器的回应,也都会有叁个Access-Control-Allow-Origin头音讯字段。

JavaScript

PUT /cors HTTP/1.1 Origin: Host: api.alice.com
X-Custom-Header: value Accept-Language: en-US Connection: keep-alive
User-Agent: Mozilla/5.0…

1
2
3
4
5
6
7
PUT /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
X-Custom-Header: value
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0…

浏览器的健康CORS乞求。上边头新闻的Origin字段是浏览器自动抬高的。下边是服务器常规的答应。

JavaScript

Access-Control-Allow-Origin: Content-Type: text/html;
charset=utf-8

1
2
Access-Control-Allow-Origin: http://api.bob.com
Content-Type: text/html; charset=utf-8

Access-Control-Allow-Origin字段是历次回应都必将饱含的
结束语

CO奥迪Q5S与JSONP的运用目标一样,可是比JSONP更加强大。JSONP只支持GET诉求,COWranglerS支持具有品类的HTTP乞请。JSONP的优势在于帮忙老式浏览器,以及能够向不援助COEnclaveS的网站呼吁数据。
原来的文章出处。WebSocket合计跨域

WebSocket
protocol是HTML5一种新的情商。它达成了浏览器与服务器全双工通讯,同期同意跨域通信,是server
push工夫的一种很好的贯彻。

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

前者代码:

JavaScript

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

node Server

JavaScript

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

node代理跨域

node中间件完成跨域代理,是透过启二个代理服务器,完结数量的倒车,也可以通过安装cookieDomainRewrite参数修改响应头中cookie中域名,完结当前域的cookie写入,方便接口登入认证。

原来的文章出处。使用node + express + http-proxy-middleware搭建四个proxy服务器

前端代码

JavaScript

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();

后端代码

JavaScript

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(三千); console.log(‘Proxy server
is listen at port 2000…’);

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…’);

nginx代理跨域

NGINX其实个人尚未怎么玩过,所以暂且也就不可能误人子弟了,原谅作者才疏尚浅~
有机缘学习商量再回来补充~~
交流

款待参预react技能栈、前端技能诗歌QQ群

前面三个技艺小说:604953717
react技术栈:398240621

参谋文书档案

1 赞 6 收藏
评论

凯旋门074网址 1

怎么是跨域

跨域,是指浏览器无法进行其他网址的台本。它是由浏览器的同源战术产生的,是浏览器对JavaScript实行的安全限制。

同源攻略限制了弹指间作为:

库克ie、LocalStorage 和 IndexDB 无法读取
DOM 和 JS 对象不只怕获得
Ajax要求发送不出去

大规模的跨域场景

所谓的同源是指,域名、协议、端口均为同样。

JavaScript

调用
非跨域 调用
跨域,主域区别
调用
跨域,子域名区别 调用
跨域,端口差别
调用
跨域,协议差别 localhost 调用 127.0.0.1
跨域

1
2
3
4
5
6
7
8
9
10
11
http://www.nealyang.cn/index.html 调用   http://www.nealyang.cn/server.php  非跨域
 
http://www.nealyang.cn/index.html 调用   http://www.neal.cn/server.php  跨域,主域不同
 
http://abc.nealyang.cn/index.html 调用   http://def.neal.cn/server.php  跨域,子域名不同
 
http://www.nealyang.cn:8080/index.html 调用   http://www.nealyang.cn/server.php  跨域,端口不同
 
https://www.nealyang.cn/index.html 调用   http://www.nealyang.cn/server.php  跨域,协议不同
 
localhost   调用 127.0.0.1 跨域

跨域的化解办法
jsonp跨域

jsonp跨域其实也是JavaScript设计方式中的一种代理格局。在html页面中经过相应的竹签从不一样域名下加载静态能源文件是被浏览器允许的,所以大家得以经过那些“犯罪漏洞”来进展跨域。一般,大家能够动态的创造script标签,再去乞求三个带参网站来贯彻跨域通讯

JavaScript

//原生的落真实意况势 let script = document.createElement(‘script’);
script.src =
”;
document.body.appendChild(script); function callback(res) {
console.log(res); }

1
2
3
4
5
6
7
8
9
10
//原生的实现方式
let script = document.createElement(‘script’);
 
script.src = ‘http://www.nealyang.cn/login?username=Nealyang&callback=callback’;
 
document.body.appendChild(script);
 
function callback(res) {
  console.log(res);
}

本来,jquery也扶助jsonp的落实格局

JavaScript

$.ajax({ url:”, type:’GET’,
dataType:’jsonp’,//央求方式为jsonp jsonpCallback:’callback’, data:{
“username”:”Nealyang” } })

1
2
3
4
5
6
7
8
9
$.ajax({
    url:’http://www.nealyang.cn/login’,
    type:’GET’,
    dataType:’jsonp’,//请求方式为jsonp
    jsonpCallback:’callback’,
    data:{
        "username":"Nealyang"
    }
})

纵然这种艺术要命好用,可是八个最大的败笔是,只好达成get诉求
document.domain + iframe 跨域

这种跨域的点子最入眼的是要求主域名同样。什么是主域名同样呢?
www.nealyang.cn aaa.nealyang.cn ba.ad.nealyang.cn
那多个主域名都以nealyang.cn,而主域名差异的就无法用此格局。

如若近年来a.nealyang.cn 和 b.nealyang.cn 分别对应指向分歧ip的服务器。

a.nealyang.cn 下有叁个test.html文件

JavaScript

<!DOCTYPE html> <html lang=”en”> <head> <meta
charset=”UTF-8″> <title>html</title> <script
type=”text/javascript” src = “jquery-1.12.1.js”></script>
</head> <body> <div>A页面</div> <iframe style
= “display : none” name = “iframe1” id = “iframe”
src=”” frameborder=”0″></iframe>
<script type=”text/javascript”> $(function(){ try{ document.domain
= “nealyang.cn” }catch(e){} $(“#iframe”).load(function(){ var jq =
document.getElementById(‘iframe’).contentWindow.$
jq.get(” console.log(data);
}); }) }) </script> </body> </html>

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
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>html</title>
    <script type="text/javascript" src = "jquery-1.12.1.js"></script>
</head>
<body>
    <div>A页面</div>
    <iframe
    style = "display : none"
    name = "iframe1"
    id = "iframe"
    src="http://b.nealyang.cn/1.html" frameborder="0"></iframe>
    <script type="text/javascript">
        $(function(){
            try{
                document.domain = "nealyang.cn"
            }catch(e){}
            $("#iframe").load(function(){
                var jq = document.getElementById(‘iframe’).contentWindow.$
                jq.get("http://nealyang.cn/test.json",function(data){
                    console.log(data);
                });
            })
        })
    </script>
</body>
</html>

使用 iframe 加载 其余域下的文书(nealyang.cn/1.html), 同期document.domain 设置成 nealyang.cn ,当 iframe 加载完成后就可以获得nealyang.cn 域下的大局对象, 此时尝试着去央求 nealyang.cn 域名下的
test.json (此时能够央浼接口),就能意识数目哀告失利了~~
惊不惊奇,意不离奇!!!!!!!

数据央求失败,目标绝非达到规定的典型,自然是还少一步:

JavaScript

<!DOCTYPE html> <html lang=”en”> <head> <meta
charset=”UTF-8″> <title>html</title> <script
type=”text/javascript” src = “jquery-1.12.1.js”></script>
<script type=”text/javascript”> $(function(){ try{ document.domain
= “nealyang.com” }catch(e){} }) </script> </head>
<body> <div id = “div1”>B页面</div> </body>
</html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>html</title>
    <script type="text/javascript" src = "jquery-1.12.1.js"></script>
    <script type="text/javascript">
        $(function(){
            try{
                document.domain = "nealyang.com"
            }catch(e){}
        })
    </script>
</head>
<body>
    <div id = "div1">B页面</div>
</body>
</html>

此刻在实行刷新浏览器,就能发掘数目这一次实在是成功了~
window.name + iframe 跨域

window.name属性可安装也许再次回到贮存窗口名称的三个字符串。他的神器之处在于name值在差别页面大概不一样域下加载后依然存在,未有更改就不会发生变化,并且能够积累相当短的name(2MB)

举例index页面伏乞远端服务器上的数码,大家在该页面下创设iframe标签,该iframe的src指向服务器文件的地址(iframe标签src能够跨域),服务器文件里安装好window.name的值,然后再在index.html里面读取改iframe中的window.name的值。完美~

JavaScript

<body> <script type=”text/javascript”> iframe =
document.createElement(‘iframe’), iframe.src =
”; document.body.appendChild(iframe);
iframe.onload = function() { console.log(iframe.contentWindow.name) };
</script> </body>

1
2
3
4
5
6
7
8
9
10
<body>
  <script type="text/javascript">
    iframe = document.createElement(‘iframe’),
    iframe.src = ‘http://localhost:8080/data.php’;
    document.body.appendChild(iframe);
    iframe.onload = function() {
      console.log(iframe.contentWindow.name)
    };
  </script>
</body>

当然,那样照旧远远不够的。

因为规定假使index.html页面和和该页面里的iframe框架的src即便分化源,则也无力回天操作框架里的其他事物,所以就取不到iframe框架的name值了,告诉您大家不是一家的,你也无须获得本身这里的数据。
既然要同源,那就换个src去指,前边说了无论怎样加载window.name值都不会调换,于是大家在index.html一样目录下,新建了个proxy.html的空页面,修改代码如下:

 

JavaScript

<body> <script type=”text/javascript”> iframe =
document.createElement(‘iframe’), iframe.src =
”; document.body.appendChild(iframe);
iframe.onload = function() { iframe.src =
”;
console.log(iframe.contentWindow.name) }; </script> </body>

1
2
3
4
5
6
7
8
9
10
11
<body>
  <script type="text/javascript">
    iframe = document.createElement(‘iframe’),
    iframe.src = ‘http://localhost:8080/data.php’;
    document.body.appendChild(iframe);
    iframe.onload = function() {
      iframe.src = ‘http://localhost:81/cross-domain/proxy.html’;
      console.log(iframe.contentWindow.name)
    };
  </script>
</body>

美好仿佛绝对美丽好,在iframe载入进度中,飞速复位iframe.src的指向,使之与index.html同源,那么index页面就会去获得它的name值了!可是实际是无情的,iframe在现实中的表现是一贯不停地刷新,
也很好明白,每一遍触发onload时间后,复位src,约等于重新载入页面,又触发onload事件,于是就不停地刷新了(然则急需的数额还能出口的)。修改后代码如下:

JavaScript

<body> <script type=”text/javascript”> iframe =
document.createElement(‘iframe’); iframe.style.display = ‘none’; var
state = 0; iframe.onload = function() { if(state === 1) { var data =
JSON.parse(iframe.contentWindow.name); console.log(data);
iframe.contentWindow.document.write(”); iframe.contentWindow.close();
document.body.removeChild(iframe); } else if(state === 0) { state = 1;
iframe.contentWindow.location =
”; } }; iframe.src =
”; document.body.appendChild(iframe);
</script> </body>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<body>
  <script type="text/javascript">
    iframe = document.createElement(‘iframe’);
    iframe.style.display = ‘none’;
    var state = 0;
    
    iframe.onload = function() {
      if(state === 1) {
          var data = JSON.parse(iframe.contentWindow.name);
          console.log(data);
          iframe.contentWindow.document.write(”);
          iframe.contentWindow.close();
        document.body.removeChild(iframe);
      } else if(state === 0) {
          state = 1;
          iframe.contentWindow.location = ‘http://localhost:81/cross-domain/proxy.html’;
      }
    };
 
    iframe.src = ‘http://localhost:8080/data.php’;
    document.body.appendChild(iframe);
  </script>
</body>

之所以如上,大家就获得了服务器再次来到的数码,但是有多少个原则是须求的:

iframe标签的跨域本领
window.names属性值在文书档案刷新后如故留存的力量

location.hash + iframe 跨域

此跨域方法和方面介绍的相比左近,同样是动态插入贰个iframe然后安装其src为服务端地址,而服务端同样输出一端js代码,也同期通过与子窗口之间的通讯来成功数据的传输。

关于锚点相信我们都早就知道了,其实就是设置锚点,让文书档案钦点的照看的职位。锚点的设置用a标签,然后href指向要跳转到的id,当然,前提是你得有个滚动条,不然也不好滚动嘛是啊。

而location.hash其实就是url的锚点。譬喻

基础知识补充完成,上边大家来讲下何以兑现跨域

设若index页面要拿走远端服务器的数额,动态的插入三个iframe,将iframe的src实行服务器的地方,那时候的top
window
和包装那些iframe的子窗口是不能够通信的,因为同源战略,所以更改子窗口的不二等秘书诀就足以了,将数据作为退换后的途径的hash值加载路线上,然后就可以通讯了。将数据加在index页面地址的hash上,
index页面监听hash的成形,h5的hashchange方法

JavaScript

<body> <script type=”text/javascript”> function getData(url,
fn) { var iframe = document.createElement(‘iframe’);
iframe.style.display = ‘none’; iframe.src = url; iframe.onload =
function() { fn(iframe.contentWindow.location.hash.substring(1));
window.location.hash = ”; document.body.removeChild(iframe); };
document.body.appendChild(iframe); } // get data from server var url =
”; getData(url, function(data) { var
jsondata = JSON.parse(data); console.log(jsondata.name + ‘ ‘ +
jsondata.age); }); </script> </body>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<body>
  <script type="text/javascript">
    function getData(url, fn) {
      var iframe = document.createElement(‘iframe’);
      iframe.style.display = ‘none’;
      iframe.src = url;
 
      iframe.onload = function() {
        fn(iframe.contentWindow.location.hash.substring(1));
        window.location.hash = ”;
        document.body.removeChild(iframe);
      };
 
      document.body.appendChild(iframe);
    }
 
    // get data from server
    var url = ‘http://localhost:8080/data.php’;
    getData(url, function(data) {
      var jsondata = JSON.parse(data);
      console.log(jsondata.name + ‘ ‘ + jsondata.age);
    });
  </script>
</body>

补偿表达:其实location.hash和window.name都是大半的,都以利用全局对象属性的主意,然后那二种办法和jsonp也是同一的,就是只好够完成get需要

postMessage跨域

那是由H5提议来的二个炫彩的API,IE8+,chrome,ff都已经匡助促成了那么些效果。那些效果也是极其的轻便,其中包罗接受音讯的Message时间,和发送音讯的postMessage方法。

发送音讯的postMessage方法是向外围窗口发送新闻

JavaScript

otherWindow.postMessage(message,targetOrigin);

1
otherWindow.postMessage(message,targetOrigin);

otherWindow指的是目的窗口,也正是要给哪二个window发送音讯,是window.frames属性的积极分子要么是window.open方法创造的窗口。
Message是要发送的音信,类型为String,Object(IE8、9不帮忙Obj),targetOrigin是限量音信接受范围,不限制就用星号
*

接受音信的message事件

JavaScript

var onmessage = function(event) { var data = event.data; var origin =
event.origin; } if(typeof window.addEventListener != ‘undefined’){
window.addEventListener(‘message’,onmessage,false); }else if(typeof
window.attachEvent != ‘undefined’){ window.attachEvent(‘onmessage’,
onmessage); }

1
2
3
4
5
6
7
8
9
10
var onmessage = function(event) {
  var data = event.data;
  var origin = event.origin;
}
 
if(typeof window.addEventListener != ‘undefined’){
    window.addEventListener(‘message’,onmessage,false);
}else if(typeof window.attachEvent != ‘undefined’){
    window.attachEvent(‘onmessage’, onmessage);
}

举个栗子

a.html()

JavaScript

<iframe id=”iframe” src=””
style=”display:none;”></iframe> <script> var iframe =
document.getElementById(‘iframe’); iframe.onload = function() { var data
= { name: ‘aym’ }; // 向neal传送跨域数据
iframe.contentWindow.postMessage(JSON.stringify(data),
”); }; // 接受domain2再次回到数据
window.addEventListener(‘message’, function(e) { alert(‘data from neal
—> ‘ + 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.neal.cn/b.html" style="display:none;"></iframe>
<script>      
    var iframe = document.getElementById(‘iframe’);
    iframe.onload = function() {
        var data = {
            name: ‘aym’
        };
        // 向neal传送跨域数据
        iframe.contentWindow.postMessage(JSON.stringify(data), ‘http://www.neal.cn’);
    };
 
    // 接受domain2返回数据
    window.addEventListener(‘message’, function(e) {
        alert(‘data from neal —> ‘ + e.data);
    }, false);
</script>

b.html()

JavaScript

<script> // 接收domain1的数据 window.add伊夫ntListener(‘message’,
function(e) { alert(‘data from nealyang —> ‘ + e.data); var data =
JSON.parse(e.data); if (data) { data.number = 16; //
管理后再发回nealyang 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 nealyang —> ‘ + e.data);
 
        var data = JSON.parse(e.data);
        if (data) {
            data.number = 16;
 
            // 处理后再发回nealyang
            window.parent.postMessage(JSON.stringify(data), ‘http://www.nealyang.cn’);
        }
    }, false);
</script>

别慌,不正是跨域么!

2017/12/27 · 基本功技艺 ·
跨域

初稿出处:
Neal_yang   

前端开辟中,跨域使我们常常蒙受的叁个标题,也是面试中不常被问到的局地难点,所以,这里,大家做个计算。小小难题,不足顾忌

相关文章