Javascript跨域请求资源

来源:互联网 发布:php读取数据库内容 编辑:程序博客网 时间:2024/06/05 07:59

目前的浏览器没有赋予Javascript脚本更大的权力来操作本地api,比如,文件,socket,等。


Javascript能够操作的东西目前仅限于浏览器创建出来的资源,比如,dom树,socke连接。


如果一个文件是Javascript(v8的js解释器引擎DLL)发起的读写操作,浏览器会拒绝。

如果一个socket是js引擎发起的,浏览器也会拒绝。


Javascript引擎可以利用(1)已经打开的连接, (2)打开指向本网站域的URL


ajax跨域请求限制实际上是js的脚本安全限制:

**** 指向其他网站的url连接必须是显示的有浏览器打开,不能有动态脚本发起。

**** 指向本站的url连接可以有动态脚本直接请求。


解决方案:


网上流行的4中解决方式,总结了一下,web前端主要可以考虑以下2种方式。

1, iframe 和 window.name 以及 contentWindow.name

参考:http://www.cnblogs.com/rainman/archive/2011/02/21/1960044.html

服务器A上有个页面App.htm的js脚本需要在客户端跨域访问服务器B上的页面data.htm

在服务器A上再创建一个空白的proxy.htm,用于修改iframe的src属性,进而改变域。


测试环境配置:

服务器A,B的ip为10.12.32.17,在客户端机器上设置域名解析,修改hosts文件

10.12.32.17           www.a.com10.12.32.17           www.b.com10.12.32.17           www.c.com10.12.32.17           www.d.com

客户端也可以是10.12.32.17,域名解析改成127.0.0.1就好了。


先看app.htm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><META http-equiv="Content-Type" content="text/html; charset=utf-8"><HTML><HEAD></HEAD><BODY>app.htm
<script>var ifr = document.createElement('iframe');ifr.src = 'http://www.b.com/data.htm';var load_domain_A = 0;/*** 这个加载完毕函数为被回调2次* 一次是data.html加载完毕的时候* 一次是proxy.htm加载完毕的时候*/ifr.onload  = function (){    if ( load_domain_A  == 0){// 说明是data.htm加载完毕        load_domain_A = 1; // 修改标记        // 修改iframe的属性,让浏览器"误"认为iframe的domain已经切换了        // 浏览器会"误"认为这个时候,跨域访问是安全的。        ifr.contentWindow.location = 'http://www.a.com/proxy.htm';        return ;    }else{        // 这个时候是proxy.htm加载完毕了        alert("[window.name]=" + ifr.contentWindow.name);        // 销毁资源        ifr.contentWindow.document.write('');        ifr.contentWindow.close();        document.body.removeChild(ifr);    }}document.body.appendChild(ifr);</script>
</BODY></HTML>


再看data.htm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><META http-equiv="Content-Type" content="text/html; charset=utf-8"><HTML><HEAD></HEAD><BODY>data.htm<script>    window.name = "[data from http://www.b.com/data.htm]";</script></BODY></HTML>

其实想想也不实用,如果可以控制data.htm,也就是www.b.com上的内容,为什么不直接实现jsonp协议,然后用动态标签去实现呢? 如果在data.htm实现jsonp的话,直接用jquery的getJSON方法就可以了,当然自己用动态标签实现也可以。


2,动态script标签

首先明确一下,动态标签,不只是jsonp才用,


1) 查询模式: 也可以创建一个动态标签,直接请求一个静态的js,这个js干什么,我们就不关心了,ie,加载一些库,带来一些配置数据,但是我们需要查询或者等待这个script标签加载执行完毕,才可以访问相应的库,或者操作相应的配置数据。


2) 回调模式:查询是不是有点麻烦啊,于是考虑回调吧,回调也不等于是jsonp,你也可以直接请求一个静态js,只不过比较死板的,这个js里面已经hardcode了一个函数调用,比如说: 

foobar ( 参数啊,配置数据啊 );

然后你在caller的这个页面(也就是创建动态script的页面)定义一个函数:

foobar( arg1, arg2){你对上面传入的参数的各种处理。}

好的,说道jsonp吧,jsonp即使让动态服务器根据页面请求参数拼接一个js函数调用语句


比如说,请求的url是这样的: http://www.b.com/data.jsp?jsoncallback=foobar

那么data.jsp, 会使用一个java语句拼接一个函数foobar的调用

resp.writeln("foobar(" + jsondata.toString() + "); ";


一旦浏览器的script标签加载完毕,发现收到这个data.jsp的响应数据刚好是一段js代码,刚好是调用自己上文定义的一个函数,真是太好了。

<script>    function foobar(jsondata){        // process jsondata    }</script><!--下面的标签加载完毕以后的等价就是一个foobar({...});的函数调用语句--><script src="http://www.b.com/data.jsp?jsoncallback=foobar" />


所以一定要记住,jsonp是一个需要后台服务器动态脚本支持的功能,服务器必须实现了jsonp协议,那么大家通信起来就很happy了。




原创粉丝点击