回头再说:Uploadify跨域上传原理-阿里云开发者社区

开发者社区> 开发与运维> 正文

回头再说:Uploadify跨域上传原理

简介:

 

《 回头再说:jQuery跨域原理 》一文提到浏览器的同源策略以及使用JsonP的方式实现跨域;在评论中金色海洋提出了一个问题:

 

我最近在用 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文件里面.

ContractedBlock.gifuploadify.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',测试结果见下面的截图

 

error 

    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和策略文件实现了跨域上传.

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

 

     测试文件下载:Web1.rar crossdomain.xml

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章