jsonp跨域的原理
1:使用script 标签发送请求,这个标签支持跨域访问
2:在script 标签里面给服务器端传递一个 callback
3:callback 的值对应到页面一定要定义一个全局函数(为什么是全局?因为服务端接收到callback函数后会返回页面中的script中去找,如果不写在全局作用域中根本找不到)
4:服务端返回的是一个函数的调用。调用的时候会吧数据作为参数包在这个函数里面。
因为同源策略的原因,不同的域之间是不能共享数据的(cookie)
有些标签可以跨域的:
1,<img>
2,<iframe>
3,<link>
4,<script>
这些标签是可以引入外部资源的,他们的特点就是拥有src/href属性,这些属性在跨域,而不是标签本身在跨域,看到这里可能你也想到了一些CSS的样式属性,比如background-image属性和border-image属性(关于这种CSS属性网上还能找到一些利用跨域它们的跨域能力实现CSS攻击的文章),也就是说凡是可以引入外部资源的属性或者标签都是可以实现跨域的。
jsonP跨域就是利用<script>标签中的src属性。
具体实现:
首先我们需要两个<script>
第一个<script>
<script>
function getData( data ){ // 定义一个获取数据的函数
console.log( data );
}
</script>
第二个<script>
在b网站发送数据请求,并且在?号后传值callback
<script src="http://www.b.com/index.php?callback=getData"></script>
$callback = $_GET['callback']; // 得到前台传来的回调函数
if( $callback ){ // 假设callback有值的话
echo $callback( { 'data':'hello' } ); // 将数据塞到函数内部,输出出去
}
这时我们写的第一个<script>标签内部的getData()函数就已经接受到了后台传的数据了。
这样我们的jsonP跨域请求已经完成。
或者:
发送请求:
<body>
<input type="button" value="script 标签发送请求,接收数据">
<script>
function getInfo(obj){
console.log(obj.username);//拿到数据 张三.
};
document.querySelector("input").οnclick=function(){
var script=document.createElement("script");
//能发跨域请求,绝对能发不跨域的请求的
script.src="05cross.php?callback=getInfo";//js 去解析,调用这个函数,就会在script 标签里面找这个函数。
document.body.appendChild(script);
/*通过js 去接收到数据.*/
//现在的数据直接浏览器拿到之后按照js 的方式去解析,所以报错
}
</script>
</body>
下面服务器返回:
<?php
//获取到的这个叫做getInfo
$_call=$_GET["callback"];
$data='{"username":"张三"}';
echo $_call."(".$data.")";
//返回到客户端就是getInfo({"username":"张三"})的调用结果
?>
jsonP的优缺点:
优点:
显而易见的简单方便,也不会有类似于浏览器兼容不了的毛病,直接响应数据,快速实现双向通信。
缺点:
1, jsonP是从其他域中加载代码执行,这时我们对外域的安全需要有一定的认识,如果它们不安全导致的问题可能会很严重,所以这时我们除了放弃jsonP没有其他办法
2,它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。