首页 > 代码库 > (转)由Uploadify插件想到的Flash无法传递Session和Cookie的问题解决
(转)由Uploadify插件想到的Flash无法传递Session和Cookie的问题解决
在ASP.NET MVC3中使用Uploadify上传文件时发现,在后台需要验证登录状态的时候,Uploadify根本无法完成验证,因此,在后台只能使用非验证状态进行文件上传 —— 众所周知,这无异于给非登录的不安分子提供了一个绝佳的机会。
为了解决这个问题,我们就需要去了解Uploadify,至少在我开始要解决这个问题的时候是这么想的.在Uploadify的官方网站的帮助文档中找到了这么专门的一节:Using Sessions with Uploadify.
这文章无疑对我们解决问题是个好的开端。也许你会问,客户端也有Session么?如果你是以服务器那种角度考虑,我可以非常肯定的告诉你,当然——没有! HTTP的请求是一个无状态请求,Session的一切存在都以客户端和服务端的交换标志而延续的。在大部分情况下,是在Cookies里面设置SessionId来达到此种目的。在客户端不支持Cookies的时候,可能会在URI中加入标志来达到同样的目的。至于更深入的讨论就不属于本文范围。这里做出说明,是想让我们的问题更能针对的解决,将问题缩小到:Uploadify如何将Cookies传递到服务端。
在上面提及的文档中,官方给出了PHP的解决方案,代码非常简单:
/*PHP在客户端初始化Uploadify的代码*/
$(‘#file_upload).uploadify({
// Your normal options here
formData : { ‘<?php echo session_name();?>‘ : ‘<?php echo session_id();?>‘ }
});
/*PHP服务端的代码*/
$session_name = session_name();
if (!isset($_POST[$session_name])) {
exit;
} else {
session_id($_POST[$session_name]); // 将当前的SessionId设置成客户端传递回来的SessionId
session_start();
}
从代码可以看出,官方处理的具体思路是这样的:1. 加载含有Uploadify的页面时,将Cookies中的SessionId写入到Uploadify中的formData中;2. 在客户端提交的时候,SessionId会被当作表单数据被Uploadify一并提交到服务端;3. 在服务端检测,将提交上来的SessionId提取出来,并将当前状态以提交的SessionId为蓝本进行操作。这样,就能对操作进行验证,达到控制的目的。
有了这个蓝本,在ASP.NET MVC3中解决起来也就不难了,按着官方的思路来即可:
1. 首先,将当前的状态存入formData中:
/*视图中的代码,使用Razor语法.*/
$("#fileupload").uploadify({
‘formData‘ : { @foreach(string k in Request.Cookies.AllKeys){
@:‘cookie_@(k)‘ : ‘@Request.Cookies[k].Value‘,
}
‘‘ : ‘‘}
})
为了完全模拟客户端状态,我们将所有的Cookies都放在了formData中,并且,为了以示区分,我们将键值名称统一用cookie_开头。
2. 客户端处理安全之后,我们就需要处理服务端了,在MVC中,我们没有PHP那种Session_id(Id)这种现成方法可以用(如果你有,请告诉我~),我们需要在Global.asax中设置,代码如下:
protected void Application_BeginRequest(object sender, EventArgs e)
{
try
{
HttpRequest request = HttpContext.Current.Request;
foreach (string k in request.Form.Keys)
{
if (k.IndexOf("cookie_") >= 0)
AppendingCookies(k.Remove(0, 7), request.Form[k], request);
}
}
catch { }
}
private void AppendingCookies(string cookieName, string cookieValue, HttpRequest request)
{
HttpCookie hc = request.Cookies.Get(cookieName);
if(null == hc)
hc = new HttpCookie(cookieName);
hc.Value = http://www.mamicode.com/cookieValue;
request.Cookies.Set(hc);
}
我们在开始请求的时候,将请求拦截,并检查请求中提交上来的表单数据,如果发现有以"cookie_"开头的数据,就将此数据提取出来,设置到当前请求的Cookies中。
恩,事情到这里,显得就很完美了,Uploadify用起来已经和普通的请求没有任何差别了。但有一个小小的缺憾,就是每次请求,无论请求那一个数据,都会进行这么一遍操作,万一要是其他表单中真有这么一个"cookie_"开头的数据,那还真就不太好了,为了解决这个问题,我们需要对操作进行一点点改进,改进后代码如下:
protected void Application_BeginRequest(object sender, EventArgs e)
{
try
{
RouteData rd = RouteTable.Routes.GetRouteData((HttpContextBase)new HttpContextWrapper(HttpContext.Current));
string c = rd.GetRequiredString("controller");
string a = rd.GetRequiredString("action");
if (c.ToLower() == "uploadfile" && a.ToLower() == "upload")
{
HttpRequest request = HttpContext.Current.Request;
foreach (string k in request.Form.Keys)
{
if (k.IndexOf("cookie_") >= 0)
AppendingCookies(k.Remove(0, 7), request.Form[k], request);
}
}
}
catch { }
}
private void AppendingCookies(string cookieName, string cookieValue, HttpRequest request)
{
HttpCookie hc = request.Cookies.Get(cookieName);
if(null == hc)
hc = new HttpCookie(cookieName);
hc.Value = http://www.mamicode.com/cookieValue;
request.Cookies.Set(hc);
}
这里uploadfile是MVC中的控制器,upload是Action,我们在操作之前,检视一下当前的请求是否是文件上传,如果是,我们再来执行这些操作,这样,出现问题的可能性就降低了。
写到这里,我们就已经完全解决Uploadify的状态问题了,甚至比官方处理的还要好些,既然这样,那就先告一段落。我们文章开始说过,这个不是Uploadify独有的问题,而是Flash的问题,因此,在使用Flash和系统做交互时,该如何处理呢?其实在解决我们文件上传验证的问题的时候,我们已经了解了处理此类问题的方法,我们完全可以参照Uploadify的处理方法来完成操作即可:
1. 将服务端的当前请求状态悉数放入到客户段准备和Flash交互的代码中(可以是JS,可以是HTML);
2. 客户端通过Flash将已经存放到客户端的请求状态封装到Flash的请求中,一并提交到服务端;
3. 服务端将Flash的请求中的Cookies信息提取出来,并设置到当前请求的Cookies中。
另外一种方法是,将Flash中的数据导出来,使用Js来进行提交,这种方式只需要将Flash中交互数据提取出来,JS的请求会自动将客户端的Cookies传递到服务端,这种方法相对来说更加简单高效。Uploadify也提供了HTML5版本,只是是收费的,但相信,用的应该就是这种方法。
本文为原创,转载请保留出处:MitchellChu‘s Blog
$(
function
(){
setTimeout(
function
(){
$(
‘#file_upload‘
).uploadify({
‘swf‘
:
‘tools/uploadify/uploadify.swf‘
,
‘uploader‘
:
‘upload.php‘
,
‘onUploadSuccess‘
:
function
(file, data, response) {
}
});
},10);
});
(转)由Uploadify插件想到的Flash无法传递Session和Cookie的问题解决