解決SWFUpload在Chrome、Firefox等瀏覽器下的問題


SWFUpload 是一個非常不錯的異步上傳組件,但是在Chrome、Firefox等瀏覽器下使用的時候會有問題。問題如下:為了防止跳過上傳頁面直接向“接受 SWFUpload上傳的一般處理程序”(假如是Upload.ashx)發送請求造成WebShell漏洞,我的系統中對於Upload.ashx進行 了權限控制,只有登錄用戶才能進行上傳。在IE下沒問題,但是在Chrome下運行報錯“用戶未登錄”。


    經過搜索得知: 因為SWFUpload是靠Flash進行上傳的,Flash在IE下會把當前頁面的Cookie發到Upload.ashx,但是Chrome、 Firefox下則不會把當前頁面的Cookie發到Upload.ashx。因為Session是靠Cookie中保存的SessionId實現的,這 樣由於當前頁面的Cookie不會傳遞給Flash請求的Upload.ashx,因此請求的文件發送到Upload.ashx就是一個新的 Session了,當然這個Session就是沒有登錄的了。

    解決這個問題的思路也很簡單,那就是手動把SessionId傳遞 給服務器,再服務器端讀出SessionId再加載Session。其實解決問題的辦法SWFUpload的Demo中已經給出了,那就是在 SWFUpload的構造函數中設置post_params參數:

swfu = new SWFUpload({
    // Backend Settings
    upload_url: "/Upload.ashx",
    post_params: {
        "ASPSESSID": "<%=Session.SessionID %>"
    },

 post_params中設定的鍵值對將會以Form表單的形式傳遞到Upload.ashx,也就是SWFUpload提供了為請求增加自定義請求參數的接口。
 
上面的代碼把當前頁面的SessionId寫到ASPSESSID值中,當用戶上傳文件后,ASPSESSID就會傳遞到服務器上了,在Global.asax的Application_BeginRequest中添加如下代碼:

var Request = HttpContext.Current.Request;
            var Response = HttpContext.Current.Response;
            /* Fix for the Flash Player Cookie bug in Non-IE browsers.
             * Since Flash Player always sends the IE cookies even in FireFox
             * we have to bypass the cookies by sending the values as part of the POST or GET
             * and overwrite the cookies with the passed in values.
             * 
             * The theory is that at this point (BeginRequest) the cookies have not been read by
             * the Session and Authentication logic and if we update the cookies here we'll get our
             * Session and Authentication restored correctly
             */
 
            try
            {
                string session_param_name = "ASPSESSID";
                string session_cookie_name = "ASP.NET_SESSIONID";
 
                if (HttpContext.Current.Request.Form[session_param_name] != null)
                {
                    UpdateCookie(session_cookie_name, HttpContext.Current.Request.Form[session_param_name]);
                }
                else if (HttpContext.Current.Request.QueryString[session_param_name] != null)
                {
                    UpdateCookie(session_cookie_name, HttpContext.Current.Request.QueryString[session_param_name]);
                }
            }
            catch (Exception)
            {
                Response.StatusCode = 500;
                Response.Write("Error Initializing Session");
            }

 其中UpdateCookie方法的定義如下:

static void UpdateCookie(string cookie_name, string cookie_value)
        {
            HttpCookie cookie = HttpContext.Current.Request.Cookies.Get(cookie_name);
            if (cookie == null)
            {
                cookie = new HttpCookie(cookie_name);
                //SWFUpload 的Demo中給的代碼有問題,需要加上cookie.Expires 設置才可以
                cookie.Expires = DateTime.Now.AddYears(1);                
                HttpContext.Current.Request.Cookies.Add(cookie);
            }
            cookie.Value = cookie_value;
            HttpContext.Current.Request.Cookies.Set(cookie);
        }

 原理:當用戶請求到達ASP.Net引擎的時候Application_BeginRequest方法首先被調用,在方法中看客戶端是否提交上來了 ASPSESSID,如果有的話則把ASPSESSID的值寫入Cookie(以"ASP.NET_SESSIONID"為Key,因為ASP.Net中 SessionId就是保存在"ASP.NET_SESSIONID"為Key的Cookie中的),Application_BeginRequest 方法后就可以從Cookie中讀取到"ASP.NET_SESSIONID"的值還原出頁面的Session了。

如果網站中還用到了Membership的FormsAuthentication驗證,則還需要把AUTHID也按照SessionID的方法進行處理,這一點是其他講到SWFUpload這個Bug處理的文章中沒有提到的。

在SWFUpload的構造函數中設置post_params參數:

swfu = new SWFUpload({
    // Backend Settings
    upload_url: "/AdminHT/UploadArticleImg.ashx",
    post_params: {
        "ASPSESSID": "<%=Session.SessionID %>",
        "AUTHID" : "<%=Request.Cookies[FormsAuthentication.FormsCookieName].Value%>"
    },

 在Global.asax的Application_BeginRequest中添加如下代碼:

try
            {
                string auth_param_name = "AUTHID";
                string auth_cookie_name = FormsAuthentication.FormsCookieName;
 
                if (HttpContext.Current.Request.Form[auth_param_name] != null)
                {
                    UpdateCookie(auth_cookie_name, HttpContext.Current.Request.Form[auth_param_name]);
                }
                else if (HttpContext.Current.Request.QueryString[auth_param_name] != null)
                {
                    UpdateCookie(auth_cookie_name, HttpContext.Current.Request.QueryString[auth_param_name]);
                }
 
            }
            catch (Exception)
            {
                Response.StatusCode = 500;
                Response.Write("Error Initializing Forms Authentication");
            }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM