在讲跨域前必须了解同源策略:同源策略,它是由Netscape提出的一个著名的安全策略。如今全部支持JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面当一个百度浏览器执行一个脚本的时候会检查这个脚本是属于哪一个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。简单的一句话就是:“若是两个页面拥有相同的协议(protocol),端口(若是指定),和主机,那么这两个页面就属于同一个源(origin)。”下图为是否同源:javascript
为了保证用户信息的安全,防止恶意的网站窃取数据。同源策略下:Cookie、LocalStorage 和 IndexDB 没法读取,DOM 没法得到,AJAX 请求不能发送。(ps:若是想更多了解同源策略能够看阮一峰大神的博客:http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html)。php
为了解决不一样源之间通信,跨域所以而生:html
方法一:JSONPhtml5
jsonp:JSONP是json with padding的简称,jsonp看起来跟json差很少,只不过是包含在函数中的json数据而已。java
callback({"name":"xiaotutu"});
由于script标签是不受同源策略影响的,它能够引入来自任何地方的js文件。而jsonp的原理就是,在客户端和服务端定义一个函数,当客户端发起一个请求时,服务端返回一段javascript代码,其中调用了在客户端定义的函数,并将相应的数据做为参数传入该函数。通常状况下,为了这个script标签可以动态的调用,咱们能够经过javascript动态的建立script标签,这样咱们就能够灵活调用远程服务了。代码以下:web
function jsonp_callback(data) { console.log(data); } function jsonpAjax(){ var url = "http://a.com/b.php?jsonp_callback=jsonp_callback"; var script = document.createElement('script'); // 发送请求 script.src = url; document.head.appendChild(script); } jsonpAjax()
当服务器接受到callback时候会返回相应的代码json
jsonp_callback({ "name": "chentutu" });
jsonp是想对来讲比较简单的,灵活的利用了<script>的不受限制从其它域加载资源。由于javascript是有效代码因此在请求完成后,就会被当即执行。跨域
方法二:<img>浏览器
跟script同样能不受其它域限制加载资源,使用它们的onload和onerror事件处理程序来肯定是否响应。但它只能用来发送GET请求,且没法获取服务端的响应文本,因此只能利用它实现一些简单的、单向的跨域通讯,例如跟踪用户的点击。你们看看下面的例子:安全
var img = new Image(); img.onload = function(){ console.log('done') img.onload = null; img = null; } img.src = "http://xx/xx.gif"
方法三:CORS
CORS(Cross-Origin Resource Sharing,跨源资源共享)是W3C小组制定的一个标准,它容许浏览器实现跨域通讯。经过创建一个XmlHttpRequest对象,CORS容许开发者象实现同源请求那样实现跨源请求。CORS(跨源资源共享)的实现目标很是简单。假设站点B想访问站点A中的某些数据,使用同源请求将不能知足这一需求。可是,经过CORS请求,站点A能够经过在部分页面中加入特殊的响应头的方法来容许站点B访问。
注意CORS只支持如下浏览器:
下面就是一个建立请求对象的代码:
function createCORSRequest(method, url) { var xhr = new XMLHttpRequest(); if ("withCredentials" in xhr) { //检查XMLHttpRequest对象是否拥有一个withCredentials属性 //withCredentials属性只属于XMLHTTPRequest2对象 xhr.open(method, url, true); } else if (typeof XDomainRequest != "undefined") { //不然,检查XDomainRequest对象 Otherwise, check if XDomainRequest. //XDomainRequest对象只存在于IE浏览器中,且被IE浏览器用来建立CORS请求 xhr = new XDomainRequest(); xhr.open(method, url); } else { //不然,CORS不被当前浏览器支持 xhr = null; } return xhr; } var xhr = createCORSRequest('GET', url); if (!xhr) { throw new Error('CORS不被支持!'); }
在默认状况下,标准的CORS请求不发送或设置任何cookie。为了在请求中包含cookie,你须要将XmlHttpRequest对象的withCredentials属性值设为true。为了达到目的,服务器端必须将Access-Control-Allow-Credentials响应头设为true。.withCredentials属性值的设置将会使跨源请求中能够包含任何cookie,开发者也能够经过使用该属性值来跨源设置任何cookie。请注意,这些cookie也可使用同源安全策略,即被跨源设置的cookie中的内容不能被同源的JavaScript脚本代码所访问,只能被设置这些cookie的源所访问。
一个使用CORS请求的完整代码示例以下所示:
//建立XHR对象 function createCORSRequest(method, url) { var xhr = new XMLHttpRequest(); if ("withCredentials" in xhr) { //Chrome/Safari/Firefox浏览器中的XHR对象 xhr.open(method, url, true); } else if (typeof XDomainRequest != "undefined") { //在IE浏览器中建立XDomainRequest对象 xhr = new XDomainRequest(); xhr.open(method, url); } else { //CORS不被支持. xhr = null; } return xhr; } //从服务器端响应中获取title标签 function getTitle(text) { return text.match('')[1]; } //建立CORS请求 function makeCorsRequest() { // bibliographica.org支持CORS请求 var url = 'http://bibliographica.org/'; var xhr = createCORSRequest('GET', url); if (!xhr) { alert('您的浏览器不支持跨源请求'); return; } //处理服务器端响应 xhr.onload = function() { var text = xhr.responseText; var title = getTitle(text); alert('来自' + url + '的响应: ' + title); }; xhr.onerror = function() { alert('跨源请求失败!'); }; xhr.send(); }
CORS分为简单和非简单模式:详细请见阮一峰大神的博客:http://www.ruanyifeng.com/blog/2016/04/cors.html。
方法四:document.domain
document.domain
让它们同域如下是document.domain实际操做的代码:
var ifr = document.createElement('iframe'); ifr.src = 'http://b.a.com/bar'; ifr.onload = function(){ var ifrdoc = ifr.contentDocument || ifr.contentWindow.document; ifrdoc.getElementsById("foo").innerHTML); }; ifr.style.display = 'none'; document.body.appendChild(ifr);
注意:若是修改了document.domain,则在某些机器上的IE678里,获取location.href有权限异常。document.domain
只能从子域设置到主域,往下设置以及往其余域名设置都是不容许的。
方法五:window.postMessage
//发送端 var win = window.open('http://b.com/bar'); win.postMessage('Hello world!', 'http://b.com'); //接收端 window.addEventListener('message',function(event) { console.log(event.data); });
想了解window.postMessage的博友能够看看张鑫旭老师的博客:http://www.zhangxinxu.com/wordpress/2012/02/html5-web-messaging-cross-document-messaging-channel-messaging/。
方法六:WebSocket
WebSocket 是HTML5一种新的协议。它实现了浏览器与服务器全双工通讯,同时容许跨域通信,是server push技术的一种很棒的实现。(不用http协议有本身的一套协议)。
在客户端的实例:
var ws = new WebSocket('ws://127.0.0.1:8080/url'); //新建一个WebSocket对象,注意服务器端的协议必须为“ws://”或“wss://”,其中ws开头是普通的websocket链接,wss是安全的websocket链接,相似于https。 ws.onopen = function() { // 链接被打开时调用 }; ws.onerror = function(e) { // 在出现错误时调用,例如在链接断掉时 }; ws.onclose = function() { // 在链接被关闭时调用 }; ws.onmessage = function(msg) { // 在服务器端向客户端发送消息时调用 // msg.data包含了消息 }; // 这里是如何给服务器端发送一些数据 ws.send('some data'); // 关闭套接口 ws.close();
详情你们仍是看红宝书591吧。