有个Discuz!论坛搬了服务器之后,曾出现一件怪事:上传头像的时候,老提示"Access denied for agent changed";后来才知道原来是UCenter缓存中关于该Discuz!的通讯密钥没更新,导致这样的结果(-_-||)。那次问题解决之后,心想,如果了解UCenter的flash上传头像机制,也许对解决这类千奇百怪的问题会有一定的帮助。
不过,真正促使我研究的则是一位Q聊了不到1个小时的HK网友。他的热情打动了我(其实还不如说我心太软 -_-||),使得我趁着求职空闲期、同时就着很久没有玩程序的手痒期,花了3天时间进行了这个功能的剥离。 UCenter的头像上传机制是这样的:
(1)安全性检查:将$_GET['input']所解密出来的和agent相关索引的变量(已经经过MD5)、和$_GET['agent'](已经经过MD5)进行对比,以此对打开flash上传页面的user agent进行检查,如果解密失败、或者两者前后不一致则判定为agent更改而拒绝操作。
(2)flash头像上传第一步:flash通过POST将原文件上传到服务器并指定$_GET['a']为uploadavatar;php根据代码,将$_FILES对应的原始文件放到临时文件夹,同时返回该临时文件的url地址供flash调用,进行裁剪。
(3)flash头像上传第二步:flash通过POST将裁剪好的图像进行编码,并分别以$_POST['avatar1']、$_POST['avatar2']、$_POST['avatar3']发送到服务器,同时指定$_GET['a']为rectavatar;php则对这3个$_POST进行解码,得出3份不同大小头像,然后写入指定位置。最后删除第一步对应的临时文件。
UCenter对应该功能的源代码其实存在一些问题:
(1)无论第一步还是第二步,php服务端其实没有判断上传的文件大小,只是依赖flash文件的前台拦截和authcode函数的加解密保护;
(2)假如上传png或者gif文件,第二步结束后,对应的临时文件将不会被删除。
(3)假如某人只是上传了第一步而不做第二步,该临时文件将一直在那里。
其实第(3)个问题并不是UCenter问题,这个还得涉及php的特性。提出来只是让大家留心,去定时清除临时文件夹的过期文件。问题(2)和问题(1)的第一步,在剥离的过程中已经进行了修复了。不过问题(1)的第二步,暂时还不知道如何处理,strlen函数也许可以解决,有时间再改吧。
这个独立程序有两个逻辑地方没有和UCenter同步:
(1)那就是不会在开始的时候对$_GET/$_POST/$_COOKIE/$_SERVER/$_FILES/$_REQUEST强制进行addslashes处理。有需要的人们,就自行在入口(upload.php)添加相关代码吧。
(2)头像上传flash文件(camera.swf)并不是来自Ucenter 1.5.1的,而是来自Discuz! NT 3.1。后者的flash文件可以指定头像处理文件服务端入口(在这个独立程序中为upload.php),而不像前者那样一定要是index.php。同是一家公司的产品,都不知道该不该说是洗具还是杯具(-_-||)。
该独立运行程序说明和下载地址:
|