CI Session类与swfupload兼容的问题
本文目前就CodeIgniter使用session类时与swfupload的不兼容问题作一个初步探讨,并给出一个并不完美的解决办法。
首先说明,swfupload与session不兼容不是CodeIgniter的问题,而是官方所说在使用flash上传文件时无法使用浏览器自身cookie的问题,所以这个不兼容普遍在其它使用了swfupload的程序中存在。
一、问题发现
这个项目因为使用了百度的UEditor,而UEditor附件上传功能使用了swfupload。上传图片同样使用了flash批量上传,服务器端输出按照规定格式后,无任何问题。
偏偏在一个附件上传中,总是出现302错误。使用chrome及ie的请求监控,都监控不到任何请求(上传文件的请求),而在上传图片时是正常的,可以监控到发送数据,发送的header以及cookie。flash net这方面没有深入研究,不知道两个flash的上传原理差别在哪里,也希望有了解的朋友可以指点下。
最终通过服务器端调试,发现请求确实存在,只是因为没有包含浏览器cookie,在上传的时候,就会出现登陆信息不符,从而被跳转到登陆页(实际是flash接收到这个跳转应答,并没有跳转)
二、解决办法
ueditor源码中给出的解决办法是将PHPSESSID及其值添加到post_params,这个post_params是swfupload上传时附带发送至服务器的内容,存在于POST数据。但是CodeIgniter的session类是使用COOKIE存储的,并没有使用php的原生session,所以,这个方法行不通。
于是看到swfupload库中有一个swfupload.cookie.js,一看内容,是将浏览器cookie附加至swfupload上传信息中,作为post发送到服务器的。那么,这个东西应该有些用处。于是引入进来。
<!--在 ueditor/dialogs/attachment/attachment.html 中引入swfupload.js之后引入cookie.js --> <script type="text/javascript" src="../../third-party/swfupload/swfupload.cookies.js"></script> //...略 <script> //...初始化swfupload参数 swfupload = new SWFUpload( settings ); //在新建swfupload上传对象后刷新cookie至flash参数 swfupload.refreshCookies(); </script>
这样,初步在服务器检测到了post参数中存在被CI的session类加密的cookie字符串。只需要在session类初始化前,把post数据转入到cookie数据就可以了
if(isset($_POST['CI_SESSION'])){ if(!empty($_POST['CI_SESSION'])){ $_COOKIE['CI_SESSION']=$_POST['CI_SESSION']; } unset($_POST['CI_SESSION']); }
即使如此,依然出现302错误,又经过一步步排查,发现是因为session开启了IP和userAgent检测的问题。
开启检测后,解密的cookie数据要经过IP和useragent对比,如果不一致,会注销session,这样,每次302之后,登陆状态也消失了。
最初,想以同cookie一样的方法把userAgent附加过去,于是先测试一下
ie9 F12开发人员工具,脚本
navigator.userAgent //输出 >> navigator.userAgent "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; BOIE9;ZHCN)"网络->开启捕获
键 值 请求 GET / HTTP/1.1 Accept text/html, application/xhtml+xml, */* Referer http://www.baidu.com/ Accept-Language zh-CN User-Agent Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; BOIE9;ZHCN) Accept-Encoding gzip, deflate Host mp3.baidu.com Connection Keep-Alive Cookie BAIDUID=CA06C20647253571679F8E26C53E4360:FG=1; BDUT=p06pCA06C20647253571679F8E26C53E4360136599347a00发现这两个userAgent并不一样。在chrome中测试无此问题。
所以,这个解决办法暂时废弃。转而去修改了session类在初始化检测userAgent的步骤
$useragent=trim(substr($this->CI->input->user_agent(), 0, 120)); if($useragent != 'Shockwave Flash'){ if ($this->sess_match_useragent == TRUE AND trim($session['user_agent']) != trim(substr($this->CI->input->user_agent(), 0, 120))) { $this->sess_destroy(); return FALSE; } }
这样即可避过swfupload上传时的userAgent检测,但这也是个潜在的漏洞,虽然CI的session经过加密存储至数据库,又有IP检测,这个userAgent检测貌似有些多余。觉得不方便其实可以直接在session配置里关闭userAgent检测
//applications/config/config.php $config['sess_match_useragent'] = FALSE;
三、总结
越是复杂的东西,越难追求完美,只能在其中寻求一个平衡点。
另外,希望了解下为什么ueditor的图片批量上传可以,而swfupload则不行。希望百度可以搞定这个问题。
或者,上传附件直接使用html表单吧。