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表单吧。