Uploadify跨域上传原理

时间:2021-02-02 17:05:57

我最近在用 uploadify + ashx 来做文件上传的功能。都测试成功了,但是发现我可以提交到其他的网站里面。

我是在本地测试了。两个网站,IP地址相同,使用端口来区分。

一个端口是8001,另一个是8002 。

两个网站都有上传文件的程序,我发现,如果我把8001端口的站点的

'script': '/_CommonPage/UploadHandler.ashx',

改成

'script': 'http://192.168.0.1:8002/_CommonPage/UploadHandler.ashx',

居然也能够成功上传文件,传到了8002对应的网站里面。

我不知道如果换成域名了,是否也是可以往不同的域名里上传文件?

如果是的话,是不是很危险?如何来验证呢? 

 

 我给出的错误解释

         看到金色海洋的问题之后,我下载下来Uploadify源码看了一下,然后非常草率的给出了一个解释,点击这里;对于这个错误的解释,园友mx1700提出了质疑;于是下班回家之后,我开始动手模拟金色海洋的环境,试图一探究竟; 

 

Uploadify工作机制

       我在VS2010里面新建了一个webApplication,在页面上使用Uploadify,页面代码如下:   

    

 



< script src ="Scripts/jquery-1.4.1.js" type ="text/javascript" ></ script >
< script src ="Scripts/jquery.uploadify.v2.1.0.js" type ="text/javascript" ></ script >
< script src ="Scripts/swfobject.js" type ="text/javascript" ></ script >
< script type ="text/javascript" >
// <![CDATA[
var id = " 55 " ;
var theString = " asdf " ;
$(document).ready(
function () {
$(
' #fileInput ' ).uploadify({
' uploader ' : ' uploadify.swf ' ,
' script ' : ' http://www.b.com:84/Uploader.ashx ' ,
' scriptData ' : { ' id ' : id, ' foo ' : theString },
' cancelImg ' : ' cancel.png ' ,
' auto ' : true ,
' multi ' : true ,
' fileDesc ' : ' Image Files ' ,
' fileExt ' : ' *.jpg;*.png;*.gif;*.bmp;*.jpeg ' ,
' queueSizeLimit ' : 90 ,
' sizeLimit ' : 4000000 ,
' buttonText ' : ' Choose Images ' ,
' folder ' : ' /uploads ' ,
' onAllComplete ' : function (event, queueID, fileObj, response, data) {

}
});
});
// ]]></script>

< input id = " fileInput " name = " fileInput " type = " file " / >

 

        通过单步调试,我发现页面上会通过swfobject.js动态加载一个Flash,我们在页面上操作的实际上是Flash.  jQuery的作用是页面、Flash、目标服务器之间的黏合剂。它定义用户上传操作在不同时机的响应函数.而在这里 我所认为“发送数据上传文件”的函数,只不过是一个用来检查服务器上是不是已经存在同名文件的函数;由于这个检查有可能是跨域,所以 Uploadify间接使用了jQuery的JsonP跨域解决方案.

 

        通过排除,我们能有一个基本的判断:文件上传是在Flash里面完成的.那么Flash里面做了什么呢?还好有uploadify.fla文件,使用Flex Builder打开这个文件来看,果然如此,很多朋友没有Flex Builde,这里贴出完整代码;可以看到,

1 // Upload each file<br>function uploadFile(file:FileReference, index:int, ID:String, single:Boolean):

    实际的上传操作,而上传不同时机使用的很多函数都是定义在jquery.uploadify.v2.1.0.min.js文件里面.

Uploadify跨域上传原理uploadify.fla

 

       现在我们能够得出这样一个结论:Uploadify本质上是一个基于Flash的jQuery上传插件.那么它到底能不能跨域呢?这里我们要考虑两个安全模型.一个是浏览器的同源策略,jQuery与目标服务器的交互是过Jsonp方式来实现回避浏览器的同源策略。还有一个就是Flash的安全沙箱,分析之前我们还是先完成金色海洋想要的实验.

 

环境准备

       我们在IIS中部署两个站点,既然是验证跨域我们为这两个站点绑定主机头;

   站点A:www.a.com 端口83 站点B:www.b.com 端口84

   

   修改Host文件(文件位置c:\Windows\System32\drivers\etc\hosts)

 

127.0.0.1 www.a.com

 

127.0.0.1 www.b.com

   注意:为了避免偶然因素的影响,后面每一次修改之后我都会重启IIS,使用新的浏览器窗口进行测试。


  1. 首先验证两个站点是否正常运行:站点A使用'script': 'http://www.a.com:83/Uploader.ashx', 站点B使用'script': 'http://www.b.com:84/Uploader.ashx',即当前域页面上传到当前域.测试通过
  2. 将站点A上传的目标服务域修改成站点B,即修改'script': 'http://www.b.com:84/Uploader.ashx',测试结果见下面的截图

 

Uploadify跨域上传原理 

    3.看到上面的Security Error了么,我们通过在站点B下面添加一个crossdomain.xml,该文件的内容如下:

 

<? xml version="1.0" encoding="UTF-8" ?>
<! DOCTYPE cross-domain-policy SYSTEM
"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd"
>
< cross-domain-policy >
< site-control permitted-cross-domain-policies ="all" />
< allow-access-from domain ="*" />
< allow-http-request-headers-from domain ="*" headers ="*" />
</ cross-domain-policy >

 

 

 

   添加了这个文件之后,站点A上传文件到站点B成功!


Uploadify跨域原理

      上面通过添加了crossdomain.xml之后就实现了跨域上传文件,关键点在于Flash的安全沙箱策略;Flash安全策略简单讲:同一个域的属于同一个沙箱,同一个沙箱的可以互相访问.如果要访问另外一个沙箱的内容就要在另外一个沙箱定义信任,这种信任策略就定义在crossdomain.xml中。在我们的实验中就是在站点B的策略文件crossdomain.xml中定义了对站点A的信任,只不过我偷懒让站点B信任所有外部域名的访问。

     对于crossdomain.xml还有两点细节:1.这个文件的要放在站点的根目录下而且文件名固定 2.跨域访问端口在1024以下必须要通过策略文件来定义信任关系。换句话说端口大于等于1024隐式开放访问权限。策略文件的详细说明请点击这里查看。

 

 

总结   

    对于金色海洋的问题解答:之所以你可以上传到另外一个端口的站点时因为IP一样,如果是上传到另外一个域名下,需要再目标服务器的根目录下添加Flash安全策略文件.

     Uploadify本质上是一个基于Flash的jQuery上传插件.跨域上传的情况牵扯到两个安全模型,一个使浏览器的同源策略,一个使是Flash的安全沙箱策略;我们组合使用jQuery的Jsonp和策略文件实现了跨域上传.

     好吧,就到这里,周末愉快