javascript中有同源策略,javascript存在跨域通讯的问题。典型例子如:Ajax没法直接请求跨域的普通文件,存在跨域无权限访问的问题。javascript
几种常见的解决方法:php
1.JSONP 2. window.name+frame 3.document.domain + iframe 4.iframe+location.hash 5.HTML5 postMessage 方法html
1、JSONPjava
web页面上只有<script><img><iframe>这些拥有“src”属性的标签是拥有跨域能力的。因此当前解决跨域的JSONP方案就是经过<script>的这一特性来实现的。web
原理:<script>标签的src属性是没有跨域的限制的。因此JSONP动态建立一个<script>标签,将本地方法名做为请求参数传递给src属性的url,服务器端获取请求中该参数即客户端的函数名,与要返回给库户端的json数据拼接成一个函数调用的javascript语句,返回给客户端,客户端获取返回的javascript语句并执行,该javascript函数的入参即为服务器端拼接的json数据,用这样的方法来实如今客户端来对异域服务器返回的请求数据进行处理。ajax
简单归纳即,JSONP返回给客户端一串javascript脚本的字符串,脚本中封装json数据。因此这个就决定了JSONP必须在服务器端对返回数据进行处理,加上callback的函数名json
JSONP 的相关ajax方法 :跨域
1.getJSON(url+"?callback=?",data,success(data,status,xhr));浏览器
例:安全
(server.php能够跨域放置,getJSON参数该为响应的地址便可)
function handleclick()
{
$.getJSON("server.php?callback=?",function(data){
alert(data.weatherinfo.city+":"+data.weatherinfo.weather);
});
}
2.get(url+"?callback=?",data,success(data,status,xhr),"jsonp");
例:
function handleclick()
{
$.get("server.php?callback=?",function(data){
alert(data.weatherinfo.city+":"+data.weatherinfo.weather);
},"jsonp");
}
3.$.ajax
例:
$.ajax({
url:"server.php",
dataType:"jsonp",
jsonp:"callback",
type:"GET",
success:function(data){
alert(data.weatherinfo.city+":"+data.weatherinfo.weather);
}
error:function(xhr,errortext,error){
console.log("requset state:"+xhr.readyState+";errorText:"+errortext);
}
});
服务器端:
server.php
<?php
header("Content-Type:text/html;charset=utf-8");
header("Cache-Control:no-cache");
$callfunc=$_GET["callback"];
$content=file_get_contents("http://www.weather.com.cn/data/cityinfo/101190101.html");
echo $callfunc."(".$content.")";
?>
ajax 和 jsonp的本质区别是ajax是经过XMLHttpRequest来获取非本页内容,不能跨域,而jsonp是经过动态添加<script>标签来获取跨域服务器返回的脚本。
缺点:1.服务器端返回给客户端javascript脚本会对客户端产生不安全因素。
2.须要服务端配合传输相应格式数据。
3.不能解决不一样域两页面之间进行javascript的调用问题。
2、HTML5 postMessage 方法
能够用 iframe.postMessage(json,"*"); 来发送数据。
用onmessage方法来获取跨域的数据
3、window.name + iframe
原理:name在浏览器环境中为一个全局/window对象的属性,且在frame中加载新页面时,name的属性值依旧保持不变。
则能够先让iframe加载跨域页面,经过window.name属性跨域传输数据,因为同源策略window.name不能访问,因此只要将iframe从新连接到本域页面,而后就能够访问window.name中的数据。
例:a.html:
<script>
var status=0;
var data;
var fr=document.createElement("iframe");
function frload(){
if(status == 1)
{
data=fr.contentWindow.name;
alert(data);
destroyfr(fr);
}
else if(status == 0)
{
status=1;
fr.contentWindow.location.href="proxy.html"
}
};
fr.src="http://xxx.com/b.html";
fr.style.display="none";
if(fr.attachEvent){
fr.attachEvent('onload',frload);
}else
{
fr.onload=frload;
}
function destroyfr(ifr)
{
ifr.src='about:blank';
try{
ifr.contentWindow.document.write('');
ifr.contentWindow.document.clear();
}catch(e){}
ifr.parentNode.removeChild(ifr);
}
document.body.appendChild(fr);
</script>
本域代理页面为proxy.html,(也能够直接设置一个空白页面about:blank)
跨域页面:b.html:
<script>
window.name='{"name":"roy","age":"20"}';
</script>
4、document.domain + iframe
原理:针对主域相同而子域不一样的两个页面,能够经过设置document.domain=“主域” 来解决。
将 http://www.f.com/a.html 和 http://m.f.com/b.html 都设置document.domain="f.com",而后在a.html中经过iframe加载b.html,则a.html 页面能够经过iframe.contentDocument.getElementById("id"); 来获取b页面数据。
5、iframe+location.hash
原理:改变页面hash不会致使页面刷新,因此经过添加或改变iframe的src连接的hash值来进行跨域传递数据
a页面建立iframe跨域请求b页面,请求参数置于hash中,b页面从location.hash中获取请求参数生成响应数据,a 和b跨域因此b页面中没法经过parent对象改变a页面的loaction.hash的值。因此须要在b.html中动态建立iframe加载一个和a同域的c页面,将响应数据置于c的loaction.hash中,而后在c页面中则能够经过parent.parent来访问a页面并经过loaction.hash来传递远程页面的返回值
缺点:数据大小有限,而且数据直接暴露在url中