什么是浏览器同源策略?同源是指域名、协议、端口号都一样,如图:注:localhost和127.0.0.1虽然都指向本机,但也是跨域的。浏览器同源策略(同源策略)。简单的说,同源策略就是浏览器为了保证用户安全,防止恶意网站窃取数据,禁止不同域之间的JS交互,限制如下行为:Cookie、LocalStorage、indexDB无法读取。无法获取DOM。无法发送AJAX请求。解决跨域CORS资源共享的方法有多种。CORS是Cross-OriginResourceSharing的缩写。是一个W3C标准。跨域资源共享机制允许Web应用服务器进行跨域访问控制,从而可以安全地进行跨域传输。对于这种方法,阮一峰老师有一篇文章专门介绍,跨域资源共享CORS的详细解释可以参考。MDN中也有关于HTTP访问控制的文档。HTTP访问控制CORS简单的说就是:请求者在头信息中增加一个Origin字段来表示请求来自于哪个来源。(协议+域名+端口)serverresponseheader信息中会多出几个字段Access-Control-Allow-Origin这个字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任何域名的请求。Access-Control-Allow-Credentials是可选的。它的值是一个布尔值,指示是否允许发送cookie。默认情况下,cookie不包含在CORS请求中。如果设置为true,则表示服务器明确允许请求中可以包含Cookie,并一起发送给服务器。该值只能设置为true。如果服务器不希望浏览器发送cookies,删除该字段即可。Access-Control-Expose-Headers是可选的。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能获取6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果要获取其他字段,必须在Access-Control-Expose-Headers中指定。上面的例子指定getResponseHeader('FooBar')可以返回FooBar字段的值。开发人员需要在AJAX中将withCredentials属性设置为true。JSONP跨域JSONP是JSONwithPadding的缩写。这是一种利用浏览器漏洞解决跨域的方法。HTML脚本元素不受浏览器的同源策略限制。即当我们请求HTML、CSS、JS文件时浏览器不会限制。所以利用这个特性,通过加载外部js文件,向其他资源发送http请求。正是因为是请求文件,所以JOSNP只能GET,不能POST。简单的说,JSONP的解决方案就是在页面上动态创建一个script标签。window.addEventListener('message',function(event){if(event.origin=='http://hwc.home.com:3000'){//同域和异域,都根据origin判断console.log(event.data)}})//bpage带有嵌套iframe消息的页面//一个页面variframe=document.getElementsByTagName('iframe')[0];window.onMessage=function(event){if(event.source==iframe.contentWindow){}//嵌套iframe除了origin也可以使用source}//iframe页面window.parent.postMessage(data,target)window.addEventListener('message',function(e){if(e.source!=window.父)返回;//子页面可以通过该方法判断是否是来自父页面windo的消息w.parent.postMessage('data','*');},false);多个窗口之间传递消息并不意味着我用浏览器打开两个页面就可以相互通信。我需要一个otherWindow和一个其他Window参考window.postMessage语法——>otherWindow.postMessage(message,targetOrigin,[transfer]);otherWindow——>对其他窗口的引用,例如iframe的contentWindow属性,执行window.open返回的window对象,或者命名或数字索引的window.frames。message-->要发送给其他窗口的数据targetOrigin-->通过窗口的origin属性指定哪些窗口可以接收message事件,其值可以是字符串“*”(表示无限制)或URI。iframe解决跨域跨域iframe跨域访问也可以在浏览器中使用带有src的标签。所有带有src属性的标签都具有跨域能力。例如:variframe=document.createElement('iframe');iframe.src='http://script.a.com/b.html';iframe.style.display='无';document.body.appendChild('iframe');//设置域值。document.domain='a.com';varuser='admin';子窗口(http://script.a.com/b.html)这样子窗口就可以获取到父窗口的数据了。1.安全。当一个网站(b.a.com)受到攻击时,另一个网站(c.a.com)会导致安全漏洞。2、如果一个页面引入了多个iframe,为了能够操作所有的iframe,必须设置相同的domain。2)location.hash+iframe如果主域不同,可以使用location.hash和window.name来解决问题。原理是使用location.hash来传值。url:http://a.com#segmentfault中的'#segmentfault'是location.hash,更改hash不会导致页面刷新,所以hash值可以用于数据传输,当然,数据容量有限。假设域名a.com下的文件test1.html要和域名b.com下的test2.html传递信息,test1.html首先创建并自动创建一个隐藏的iframe,iframe的src指向域名b.com页面下的test2.html,此时的hash值可用于传参。test2.html响应请求后,会通过修改test1.html的hash值来传输数据(因为两个页面不在同一个域,IE和Chrome不允许修改parent.location的值。hash,所以需要使用a.com域名下的代理iframe;火狐可以修改)。同时在test1.html中加入一个定时器,判断一段时间后location.hash的值是否有变化,如果有变化则获取hash值。a.com下的test1.htmlfunctionstartRequest(){variframe=document.createElement('iframe');iframe.style.display='无';iframe.src='http://www.b.com/test2.html#paramdo';document.body.appendChild(iframe);}functioncheckHash(){try{vardata=location.hash?location.hash.substring(1):'';if(console.log){console.log('现在数据为'+data);}}catch(e){};}setInterval(checkHash,2000);b.com域名下的test2.html//模拟一个简单的参数处理操作switch(location.hash){case'#paramdo':callBack();休息;case'#paramset'://dosomething...break;}functioncallBack(){try{parent.location.hash='somedata';}catch(e){//ie和chrome的安全机制无法修改parent.location.hash,//所以使用b.com域下的中间代理iframevariframeproxy=document.createElement('iframe');iframeproxy.style.display='无';iframeproxy.src='http://a.com/test3.html#somedata';//注意文件在“a.com”域下document.body.appendChild(iframeproxy);}}a.com域名下的test3.html//因为parent.parent和本身属于同一个域,所以可以更改location.hash的值parent.parent.location.hash=self.location.hash。子串(1);缺点,数据暴露在url中。3)window.name+iframe如果主域不同,可以用location.hash和window.name解决。iframe的src属性从外域传递到本域,通过iframe的window.name将跨域数据从外域传递到本域。这巧妙地绕过了浏览器的跨域访问限制,但同时又是一种安全操作。一共有三个页面:a.com/test1.html:应用页面a.com/proxy.html:代理页面,需要和应用页面同域。b.com/test2.html:存放应用页面需要的数据页面(数据页面)的具体流程:1)应用页面创建iframe,src指向数据页面。数据页会将数据附加到iframe的window.name上。b.com/test2.htmlcode2)Listen到应用页面iframe的onload事件,并在事件中设置iframe的src指向本域的代理文件(代理页面和应用页面在同一个域,可以相互通信)其他。)a.com/test1.html代码3)获取数据后销毁iframe,释放内存。这也保证了安全性。(不被其他域iframe访问)window.topschemewindow.top方法可以访问最顶层的window对象,可以得到最顶层的window对象的属性和方法,以便childframework操作父页面的交互。window.parent可以获得父框架的窗口对象。1)a页面代码2)页面b的代码3)c页面代码cookie和WebSocket协议跨域cookie除了exprise这个属性还有一个path属性,用来设置可访问的cookie路径,默认是在当前cookie页面的子目录下可以访问,但是默认我们是访问不到的这个cookie在其他父目录下,这时候我们可以通过设置cookie来实现这个功能上面说了,但是如何实现跨域之间的值传递,其实除了路径之外,cookie里面还有域。域属性可以实现跨域,但是必须保证两个域名有共同的部分。什么是公共部分?即www.qq.com和www.sport.qq.com的域名都是qq.com,body的使用方法是将domain设置为同一部分的域名,如下:document.cookie="name=value;expires=date;path=/;domain=qq.com"另外,我们在使用cookie的时候还需要注意的是cookie的编码问题,因为cookie不支持逗号、空格、分号,所以在设置cookie的时候需要使用escape()对输入信息进行转码,以及然后使用unescape()转换回来。WebSocket对象提供了一个API,用于创建和管理WebSocket连接,以及通过该连接发送和接收数据。WebSocket构造方法接受一个必需参数和一个可选参数:WebSocketWebSocket(inDOMStringurl,inoptionalDOMStringprotocols);WebSocketWebSocket(在DOMStringurl中,在可选的DOMString[]协议中);url:表示要连接的URL。这个URL应该是响应WebSocket的地址。协议可以是单个协议名称字符串或包含多个协议名称字符串的数组。这些字符串用于表示子协议,它允许服务器实现多个WebSocket子协议(例如,您可能希望通过制定不同的协议来处理不同类型的交互)。如果未指定此参数,则默认为空字符串。(可选)构造函数方法可能会抛出以下异常:SECURITY_ERR尝试连接的端口被阻止。WebSocket协议是HTML5中的一个新协议。实现了浏览器和服务器的全双工通信,同时允许跨域通信,是服务器推送技术的一个很好的实现。原生的WebSocketAPI使用起来不是很方便。我们使用Socket.io,它很好地封装了webSocket接口,提供了更简单灵活的接口,同时为不支持webSocket的浏览器提供了向后兼容性。详见前端常用跨域解决方案参考文档H5新接口window.postMessageMDNHTTP访问控制CORSMDN跨域资源共享CORS详解JavaScript跨域总结及解决Domain方法H5新接口webSocketMDN