1.为什么会出现跨域问题
web浏览器中包含JavaScript解释器,也就是说,一旦载入Web页面,就可以任意的JavaScript代码在计算机里执行。安全隐患也就随之而来,所以由Netscape提出了一个著名的安全策略——同源策略,即JavaScript脚本不能读取从不同服务器载入的文档的内容。
2.同源策略的具体情况
一个完整的url地址包括:
协议名://域名:端口号/资源路径
URL |
说明 |
是否允许通信 |
http://www.a.com/index.html ftp://www.a.com/detail.html |
协议名不同 |
不允许 |
http://www.a.com/index.html http://www.b.com/detail.html |
协议名相同,域名不同 |
不允许 |
http://www.a.com:8000/index.html http://www.a.com:3000/detail.html |
协议名和域名都相同,端口号不同 |
不允许 |
http://www.a.com/index.html http://70.80.90.00 /detail.html |
协议名相同,假设ip地址表示的是同一个网址 |
不允许 |
http://www.a.com/index.html http://www.a.com/detail.html |
协议名相同,域名相同,端口号相同 |
允许 |
总结:如果协议名、主机名或者端口号不同,就是跨域,即使是ip地址和主机名代表同一个网址。
3.跨域问题的几种解决方案
(1).动态创建script
因为script不受同源策略的影响,所以用js动态的加载url,达到跨域。
function loadScript(url, func) { var head = document.head || document.getElementByTagName(‘head‘)[0]; var script = document.createElement(‘script‘); script.src = url; script.onload = script.onreadystatechange = function(){ if(!this.readyState || this.readyState==‘loaded‘ || this.readyState==‘complete‘){ func(); script.onload = script.onreadystatechange = null; } }; head.insertBefore(script, 0); } window.baidu = { sug: function(data){ console.log(data); } } loadScript(‘http://suggestion.baidu.com/su?wd=w‘,function(){console.log(‘loaded‘)});
(2).jsonp
JSON是一种基于文本的数据交换方式,以键值对的形式存储数据,轻量级数据格式,适用互联网传递。而JSONP是一种非正式的传输协议,该协议的原理是:web客户端通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成js格式文件(JSON后缀,封装客户端需要的数据),用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback函数作为函数名来包裹住JSON数据,这样客户端就可以使用JSON数据进行数据处理了。
//jQuery实现jsonp跨域的方法: //$.JSON方法: $.getJSON({‘myUrl?callback=?’,function(data){ //处理data数据 }); //$.ajax方法: $.ajax({ type:”get”, url:”http://www.baidu.com/..”, datatype:”jsonp”, jsonp:”callback”,//用于获得jsonp回调函数名的参数名,一般默认为callback jsonpCallback:”func()”,//自定义的jsonp回调函数名称 success:function(json){ console.log(json); }, error:function(err){ console.log(err); } });
(3).postMessage
在 HTML5 中, window 对象增加了一个非常有用的方法:
otherWindow.postMessage(message, targetOrigin);
otherWindow:调用的window;message:发送的消息或对象;targetOrigin:目标的源,* 表示任意。
window.addEventListener("message", receiveMessage, false); function receiveMessage(event) { var origin = event.origin || event.originalEvent.origin; // For Chrome, the origin property is in the event.originalEvent object. if (origin !== "http://example.org:8080") return;event.source.postMessage("the data is"
,
event.origin);
}
(4)、使用CORS跨域
CORS(跨来源资源共享)是一份浏览器技术的规范,提供了web服务器从不同网域传来沙盒脚本的方法,以避开浏览器的同源策略,是JSONP模式的现代版。
①. 客户端 使用绝对地址
xhr.open("GET", "http://blog.csdn.net/api", true);
②. 服务器
服务器端对于CORS的支持,主要就是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问。
在PHP中:只需要使用如下的代码设置即可。
<?php
header("Access-Control-Allow-Origin:*");
以上的配置的含义是允许任何域发起的请求都可以获取当前服务器的数据。这样所有域的请求都被允许会造成潜在的不安全性。所以我们应该尽量有针对性的对限制安全的来源,比如限制只能从博客园上请求
Access-Control-Allow-Origin: http://www.cnblogs.com
(5).web socket(ws协议)
var socket = new WebSockt(‘ws://www.baidu.com‘);//http->ws; https->wss
socket.send(‘hello WebSockt‘);
socket.onmessage = function(event){
var data = event.data;
}