您的位置 » 首页 » 编程开发 » 前端开发:ajax跨域之JSONP获取数据

前端开发:ajax跨域之JSONP获取数据

发表于4年前 | 作者: seay | 分类: 编程开发 | 孵化于:2013年05月04日 | 文章热度:4,417 次 全屏阅读

显示不全请点击全屏阅读

某个站点分为静态产品介绍页面(或由于某原因需要静态化),和一个独立的在线应用程序。静态产品页面属于www.a.com下,而在线应用程序作为一个相对独立的系统存在于app.a.com上。

在www.a.com上需要显示在线应用程序(app.a.com)中用户的登录状态及简单的用户信息。由于需要实时的在静态页面中显示用户登录状态,在线应用程序提供了一个用户接口来输出当前用户的登录信息,静态页面采用ajax方式动态获取。

问题在于www.a.com和app.a.com分属于不同子域,无法通过ajax直接进行通信。

思路分析:

由于同源策略的限制,XMLHttpRequest只允许请求当前源(包含域名、协议、端口)的资源。

如众周知,script标签经常被用来加载不同域下的资源,例如在www.a.com可以使用http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js这个js文件,可以绕过同源策略。

同样的,可以通过使用script标签来进行跨域请求,但是怎么获取异域源返回的数据呢?

有这样一种方式:如果请求的这个远程数据本身就是一段可执行的js,那么这些js会被执行(相当于eval)。即,若在www.a.com中存在一个showUserStatus()的js函数,它的作用是在www.a.com显示当前用户状态,只要给它传递当前用户的状态数据就可以了。那么利用script标签请求的app.a.com中,输出数据为:showUserStatus(data),那么将会执行www.a.com中的showUserStatus(),用户当前的状态就在静态页面上显示了。

使用JSON来传递javascript对象是一种最简单的方式了,这样的跨域通讯方式称为JSONP。

解决方案:

1. 静态页面上的js:

<script type="text/javascript">
	function showUserStatus(data) {
		alert(data.txt);
	}
</script>
<!--将函数名showUserStatus传递过去-->
<script type="text/javascript" src="http://app.a.com/userStatus.php?callback=showUserStatus"></script>

2. 远程php接口:

$get = $_GET;
$rtData = array(
	'uID'	=> 10000,
	'name'	=> 'Zhangsf',
	'txt'	=> 'Welcome ZhangSanFeng',
);

// 获取传递来的函数名,并拼凑完整的函数执行体
echo $get['callback'] .'('. json_encode($rtData) .')';

这里输出的格式为:

showUserStatus({"uID":10000,"name":"Zhangsf","txt":"Welcome ZhangSanFeng"})

可以看出,输出的是一个可执行的js函数体。

总结:

需要注意的是:JSONP实际上是一种脚本注入(Script Injection)方式,存在一定的安全隐患。

jQuery的书写方法如下:

var url = 'http://app.a.com/userStatus.php?callback=?';

$.getJSON(url, function(data){
	alert(data.txt)
});

抓包发现会产生类似于http://app.a.com/userStatus.php?type=json&callback=jsonp1261223089741&_=1261223089747的请求地址,问号被替换为一个带时间戳的回调函数名。

 

原文:http://www.impng.com/web-dev/ajax-crossdomain-by-jsonp.html

Tags:

前端开发,

如果您喜欢我的博客,欢迎点击图片定订阅到邮箱填写您的邮件地址,订阅我们的精彩内容: 也可以点击链接【订阅到鲜果】

如果我的想法或工具帮助到了你,也可微信扫下方二维码打赏本人一杯咖啡


来自 Seay互联网安全博客
本文地址:http://www.cnseay.com/2785/
文章版权说明请看置顶文章,尊重作者,转载请以链接形式标明原文地址

马上分享给你的朋友吧~

发表评论

你的大名(必填)

你的邮箱(必填)

评论内容(必填)