以前写过一片post是讲js跨站点通讯的,自觉似乎没有整理清楚,接下来重新整理一下。
javascript 使用xmlhttp对象无法cross domain进行请求已经成了尝试,可是很多时候还是需要跨站点进行数据传输。比如google personal homepage的widget可以放在任意的外部站点上正常工作,看似神奇,其实也就是利用了ajax patterns 里面将的一种叫做 script ondemand的技术实现的,使用这种技术进行跨站点通讯的核心原理是:
- http://a.com/a.html中的javascript向当前页面的<head>标记里面写入一个<script>标记,这个标记的src属性指向需要进行数据请求的http://b.com/data.php页面,于是浏览器便会向该地址发送加载脚本的请求
- 此时b.com的data.php页面就返回一段包含了客户端js回调函数与返回数据的脚本,让该脚本执行原先在a.com的a.html种事先写好的回调函数,并将数据传给该函数
客户端javascript代码如下:
XSSRequest = { stack_callback : {}, request : function(url,callback){ var cid = this._generateGuid(); var func_cb = callback || function(){}; url += ( url.match(/\?/) ? '&' : '?') + 'requestId=' + cid + '&callback=XSSRequest.response; var stackObj_cb = {}; stackObj_cb.requestId = cid; stackObj_cb.function_callback = func_cb; stackObj_cb.url = url; this.stack_callback[cid] = stackObj_cb; var s = document.createElement('script'); s.type = 'text/javascript'; s.src = url; document.getElementsByTagName('head')[0].appendChild(s); }, response : function(requestId,responseObj){ if(this.stack_callback[requestId]){ (this.stack_callback[requestId].function_callback)(responseObj); delete this.stack_callback[requestId]; } }, _generateGuid : function(){ var hex = new Array( '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'); var outB = '{'; for (count = 0; count < 32; count++){ if ((count == 8) || (count == 12) || (count == 16) || (count == 20)) outB += '-'; outB += hex[ Math.floor(Math.random() * 16)]; } return outB.toUpperCase() + '}'; } }
当调用XSSRequest.request(url,function(responseObj){})方法是,会产生一个形如http://b.com/data.php?requestId=xx-xx-xx&callback=XSSRequest.response的请求,之后服务器应该返回的字符串如下:
XSSRequest.response(’xx-xx-xx’,{});
后一个{}是返回数据的JSON对象。
如此一来,一个通用的cross domain 通讯框架就建立起来了,其次就是服务器端的支持了,这种简单的字符串输出相信任何一种语言都能胜任,不再赘述。
同时,大家可以比较一下,我构建的这个跨域通讯方案与这篇文档的方案哪个比较方便使用。
Technorati: javascript, ajax, XSS, cross domain