js中的跨域问题
示例代码在E/AjaxGGW/跨域问题,参考书签掘金(正确面对跨域,别慌)
1. 跨域:浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript实施的安全限制
2. 同源策略限制了以下行为:
Cookie、LocalStorage和IndexDB无法读取
DOM和JS对象无法获取
Ajax请求发送不出去
3. 常见的跨域场景
同源:域名、协议、端口均相同
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 跨域,协议不同
4. 跨域的解决办法
1)jsonp跨域
在html页面中通过相应的标签从不同的域名下加载静态资源文件是被浏览器允许的。一般,我们可以动态的创建script标签,再去请求一个带参网址来实现跨域通信。
但是,最大的缺陷是,只能实现get请求
$(function(){ /*jQuery支持jsonp的实现方式 */ $.ajax({ url:"www.baidu.com", type:"GET", dataType:"jsonp", //请求方式为:jsonp jsonpCallback:"callback", data:{ "username":"yaofan" } }) })
2)document.domain + iframe跨域(1.html和document.domain+iframe跨域.html)
最主要的要求是主域名相同,需要两个html页面
<!-- 这种方式最主要的要求是主域名相同,假设目前a.nealyang.cn和b.nealyang.cn分别对应指定不同的ip服务器 a.nealyang.cn下有一个test.html文件 b.nealyang.cn下有一个1.html文件 --> <p>A页面</p> <!-- 利用iframe加载其他域下的文件 ,src中 --> <iframestyle = "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" //将document.domain设置为nealyang.cn,当iframe加载完毕后就可以获取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>
3)window.name + iframe跨域(origin.html和target.html 不是掘金里的)
window.name属性可设置或者返回存放窗口名称的一个字符串。她的神奇之处在于,name值在不同页面或者不同域下加载依旧存在,没有修改就不会发生改变,并且可以存储非常长的name(2MB)
假设index页面请求远端服务器上的数据,我们在该页面下创建iframe标签,该iframe的src指向服务器文件的地址(iframe标签src可以跨域),服务器文件里设置好window.name的值,然后在index.html里面读取该iframe中的window.name的值
如果index.html页面和该页面里的iframe框架的src如果不同源,则无法操作框架里的任何东西。两个页面处于不同域,源页面并不能获得目标页面的name值,因为name值只对于同一个域中的页面是可见的。
4)Location.hash + iframe跨域
此跨域方法和上面介绍的比较类似,一样是动态插入一个iframe然后设置其src为服务端地址,而服务端同样输出一端js代码,也同时通过与子窗口的通信来完成数据的传输。
而location.hash其实就是url的锚点,比如http://www.nealyang.cn#Nealyang的网址打开后,在控制台输入location.hash就会返回#Nealyang的字段。
【注】其实location.hash和window.hash都是差不多,都是利用全局对象属性的方法,然后这两种方法和jsop也是一样的,就是只能实现get请求
<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.removeChild(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>
5)postMessage跨域(a.html 和 b.html)
这是由H5提出来的一个炫酷的API,包括发送信息的postMessage方法和接受信息的Message时间。
① 发送信息的postMessage方法是向外界窗口发送信息
otherWindow.postMessage(message,targetOrigin);
l otherWindow指的是目标窗口,是window.frames属性的成员或者是window.open方法创建的窗口。
l Message是要发送的消息,类型是String、Object
l targetOringin是限定消息接收范围,不限制用星号*
② 接受信息的message事件
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); }
6) 跨域资源共享CORS
目前主流的跨域解决方案
1)简介
CORS是一个W3C标准,全称是“跨域资源共享”(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而客服了AJAX只能同源使用的限制。
CORS需要浏览器和服务器同时支持。
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
相关推荐:
以上就是js中的跨域问题的详细内容,更多请关注其它相关文章!