浅谈前端跨域

一、什么是跨域?

跨域简朴的明白就是JavaScript同源战略的限定。是出于平安的斟酌,a.com域名下的js不能操纵b.com或许c.com域名下的对象。
当协定、子域名、主域名、端口号中恣意一个不雷同时,都算作差别域。差别域之间互相请求资本,就算叫“跨域”。

一个一般的域名地点构成(图片来自网络资本):
《浅谈前端跨域》

注重:跨域不是请求宣布出去,请求能够一般发出,服务器也能收到并返回效果,只是效果被浏览器所阻拦了。

附上一张参考图,便于人人深切明白(图片来自网络资本)
《浅谈前端跨域》

二、什么是同源战略与限定

同源战略限定了从同一个源加载的文档或剧本怎样与来自另一个源的资本举行交互。这是一个用于断绝潜伏歹意文件的主要平安机制。这是一种庇护用户信息,防备歹意身份捏造的一种平安机制。
同源战略限定的内容:

  1. Ajax请求不能一般举行。
  2. Cookie、LocalStoage、indexDB等没法读取。

3.DOM 没法取得。

不过,有几个标签却能够允许跨域请求资本(能够作为处置惩罚跨域的一种计划)。

1.<img src=”xxxx” alt=””>

2.<link rel=”stylesheet” href=”xxx”>

3.<script src=”xxx”></script>

三、处置惩罚跨域要领一——JSONP

JSONP是跨域通讯最经常运用的要领,其最大的特性就是简朴实用、兼容性好,可用于处置惩罚主流浏览器的跨域数据接见的题目。
瑕玷是仅支撑get要领具有局限性。
它的基本思想是,在网页中增加一个<script>标签,像服务器请求JSON数据。它须要服务器端的合营,服务器收到请求后,将数据放在指定名字的回调函数中传返来。

 <script type="text/javascript">
    function foo(data) {
        console.log(data.msg);
    }
</script>
<script type="text/javascript" src="http://xxx.com/xx?callback=foo"></script>

注重,该请求的查询字符串有一个callback参数,用来指定回调函数的名字,这关于JSONP是必需的。

由于<script>元素请求的剧本,直接作为代码运转。这时候,只需浏览器定义了foo函数,该函数就会马上挪用。作为参数的JSON数据被视为JavaScript对象,而不是字符串,因而避免了运用JSON.parse的步骤。

jQuery的jsonp情势

JSONP都是GET和异步请求的,不存在其他的请求体式格局和同步请求,且jQuery默许就会给JSONP的请求消灭缓存

$.ajax({
url: "http://xxx/xx",
dataType: "jsonp",
type: "get",//能够省略
jsonpCallback: "fn",//->自定义传递给服务器的函数名,而不是运用jQuery自动天生的,可省略
jsonp: "jsonp",//->把传递函数名的谁人形参callback变成jsonp,可省略
success: function (data) {
    console.log(data);
} });

四、处置惩罚跨域要领二——CORS

CORS是跨源资本分享(Cross-Origin Resource Sharing)的缩写。它是W3C规范,是跨源AJAX请求的基础处置惩罚要领。比拟JSONP只能发GET请求,CORS允许任何范例的请求。瑕玷是兼容性不如JSONP。

CORS请求浏览器(>IE10)和服务器的同时支撑,是跨域的基础处置惩罚要领,由浏览器自动完成。因而,完成CORS通讯的关键是服务器。只需服务器完成了CORS接口,就能够跨源通讯。
服务器端做的小修改:

header(“Access-Control-Allow-Origin:*”);

header(“Access-Control-Allow-Methods:POST,GET”);

//在服务器端设置同源战略地点

router.get("/userlist",function (req, res,next) {
var user = {
        name: 'Mr.Cao',
        gender: 'male',
        career: 'IT Education'
    };
res.writeHeader(200, {"Access-Control-Allow-Origin": 'http://localhost:63342'});
res.write(JSON.stringify(user));
res.end(); });

在相应头上增加 Access-Control-Allow-Origin 属性,指定同源战略的地点。同源战略默许地点是网页的自身。只需浏览器检测到相应头带上了CORS,而且允许的源包含了本网站,那末就不会阻拦请求相应。

五、处置惩罚跨域要领三——WebSocket

WebSocket是一种通讯协定,运用ws://(非加密)和wss://(加密)作为协定前缀。该协定不实行同源政策,只需服务器支撑,就能够经由过程它举行跨源通讯。
下面是一个例子,浏览器发出的WebSocket请求的头信息

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com

上面代码中,有一个字段是Origin,示意该请求的请求源(origin),即发自哪一个域名。

恰是由于有了Origin这个字段,所以WebSocket才没有实行同源政策。由于服务器能够依据这个字段,推断是不是允许本次通讯。假如该域名在白名单内,服务器就会做出以下回应。

六、处置惩罚跨域要领四——跨文档通讯 API/片断辨认符/window.name

假如两个网页差别源,就没法拿到对方的DOM。典范的例子是iframe窗口和window.open要领翻开的窗口,它们与父窗口没法通讯。

关于完整差别源的网站,如今有三种要领,能够处置惩罚跨域窗口的通讯题目。

6.1 片断辨认符

片断标识符(fragment identifier)指的是,URL的#号背面的部份,比方 http://xxx.com/x.html#fragmen…。假如只是转变片断标识符,页面不会从新革新。
父窗口能够把信息,写入子窗口的片断标识符。

  var src = originURL + '#' + data;
 document.getElementById('myIFrame').src = src;

子窗口经由过程监听hashchange事宜获得关照。

window.onhashchange = checkMessage;    
function checkMessage() {
  var message = window.location.hash;
  // ...
}

6.2 window.name
浏览器窗口有window.name属性。这个属性的最大特性是,不管是不是同源,只需在同一个窗口里,前一个网页设置了这个属性,后一个网页能够读取它。

父窗口先翻开一个子窗口,载入一个差别源的网页,该网页将信息写入window.name属性。

window.name = data;

接着,子窗口跳回一个与主窗口同域的网址。

  location = 'http://parent.url.com/xxx.html';

然后,主窗口就能够读取子窗口的window.name了。

var data = document.getElementById('myFrame').contentWindow.name;

这类要领的长处是,window.name容量很大,能够安排异常长的字符串;瑕玷是必需监听子窗口window.name属性的变化,影响网页机能。

6.3 window.postMessage
上面两种要领都属于破解,HTML5为了处置惩罚这个题目,引入了一个全新的API:跨文档通讯 API(Cross-document messaging)。
这个API为window对象新增了一个window.postMessage要领,允许跨窗口通讯,不管这两个窗口是不是同源。

举例来说,父窗口http://aaa.com向子窗口http://bbb.com发音讯,挪用postMessage要领就能够了。

var popup = window.open('http://bbb.com', 'title');
popup.postMessage('Hello World!', 'http://bbb.com');

postMessage要领的第一个参数是详细的信息内容,第二个参数是吸收音讯的窗口的源(origin),即”协定 + 域名 + 端口”。也能够设为*,示意不限定域名,向一切窗口发送。
子窗口向父窗口发送音讯的写法相似。

window.opener.postMessage('Nice to see you', 'http://aaa.com');

父窗口和子窗口都能够经由过程message事宜,监听对方的音讯。

window.addEventListener('message', function(e) {
  console.log(e.data);
},false);

message事宜的事宜对象event,供应以下三个属性。

event.source:发送音讯的窗口
event.origin: 音讯发向的网址
event.data: 音讯内容

七 、处置惩罚跨域要领五-document.domain

Cookie 是服务器写入浏览器的一小段信息,只要同源的网页才同享。然则,两个网页一级域名雷同,只是二级域名差别,浏览器允许经由过程设置document.domain同享 Cookie。

举例来说,A网页是http://w1.example.com/a.html,B网页是http://w2.example.com/b.html,那末只需设置雷同的document.domain,两个网页就能够同享Cookie。

document.domain = 'example.com';

如今,A网页经由过程剧本设置一个 Cookie。

document.cookie = "test1=hello";

B网页就能够读到这个 Cookie。

var allCookie = document.cookie;

注重,这类要领只实用于 Cookie 和 iframe 窗口,LocalStorage 和 IndexDB 没法经由过程这类要领。

    原文作者:alisa
    原文地址: https://segmentfault.com/a/1190000019291424
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞