最近在研究有關.net mvc項目中的session失效問題,下面小編把研究過程給大家共享下,大家可以參考下。
最近解決基於.net mvc項目的session失效問題,這個跟大家聊聊。
1.問題分析
.net mvc中,Session失效需要考慮幾種情況:
•基於權限認證的Action,使用非Ajax請求;
•基於權限認證的Action,使用JQueryt Ajax請求;
•基於權限認證的Action,使用.net mvc封裝的Ajax請求;
•無權限認證的Action,使用非Aajx請求;
•無權限認證的Action,使用原生JQuery Ajax請求;
•無權限認證的Action,使用.net mvc封裝的Ajax請求;
基於權限認證的Action,session失效後AuthorizeAttribute都可以攔截,並在HandleUnauthorizedRequest方法中處理;無權限認證的Action需要在自定義的filter中,根據新建Session與已請求Session的區別進行判斷和處理。
2.基於權限認證的非Ajax請求
Authorize filter優先於其他功能過濾器執行,因此這裡繼承AuthorizeAttribue,在HandleUnauthorizedRequest中處理session請求。
public class AuthorizeOfHandleUnAuthorizeAttribute:AuthorizeAttribute { protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { //session失效重定向到登錄頁面 filterContext.Result = new RedirectToRouteResult( new RouteValueDictionary(new { Controller = "Login", Action = "Login" })); } }
3.基於權限認證的Ajax請求
Ajax請求的Action在系統中存在兩種返回結果:JsonResult和PartialViewResult。
•JsonResult理論上可以通過在返回的結果上增加session超期屬性,客戶端進行判斷即可。但是考慮到項目已經完成,在所有ajax請求上增加判斷邏輯有些繁瑣。
服務端代碼處理ajax請求:
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { //ajax請求session超期處理 if (filterContext.HttpContext.Request.IsAjaxRequest()) { filterContext.HttpContext.Response.AppendHeader("sessionstatus","timeout"); filterContext.HttpContext.Response.End(); return; } filterContext.Result = new RedirectToRouteResult( new RouteValueDictionary(new { Controller = "Login", Action = "Login" })); }
客戶端代碼(這種處理方式對於返回結果為PartialViewResult的Action是不適用的):
onSuccess: function (xhr, status) { //獲取響應頭,sessionstatus, var sessionstatus = xhr.getResponseHeader("sessionstatus"); if (sessionstatus == "timeout") { window.location = "/Login/Login"; } }
•PartialViewResult情況的存在,直接否定上面的設想。項目中大部分Ajax請求都是基於.net mvc封裝的,直接更新指定div。
為了不做大量更改、且統一處理兩種返回結果的ajax請求,找到了另外一種方法
jQuery.ajaxSetup()
該函數用於更改jQuery中AJAX請求的默認設置選項。之後執行的所有AJAX請求,如果對應的選項參數沒有設置,將使用更改後的默認設置。
因此我們的客戶端代碼可以這樣統一處理:
//解析ajax請求session超時問題 $.ajaxSetup({ complete: function(xmlHttpRequest, textStatus) { var sessionStatus = xmlHttpRequest.getResponseHeader("sessionstatus"); if (sessionStatus === "timeout") { window.location = "/Login/Login"; } } });
本以為到這裡就萬事大吉啦,結果一不小心又發現一個問題,基於.net mvc的jquery.unobtrusive-ajax封裝的ajax請求調用,沒有達到攔截處理的效果。經過反復調試無果,最終還是注意到上面那段話
jQuery.ajaxSetup()該函數用於更改jQuery中AJAX請求的默認設置選項。之後執行的所有AJAX請求,如果對應的選項參數沒有設置,將使用更改後的默認設置。
這裡說的比較明白了,那肯定就是jquery.unobtrusive-ajax封裝的時候搗的鬼啦,翻開源碼一看果然如此:
$.extend(options, { type: element.getAttribute("data-ajax-method") || undefined, url: element.getAttribute("data-ajax-url") || undefined, cache: !!element.getAttribute("data-ajax-cache"), beforeSend: function (xhr) { var result; asyncOnBeforeSend(xhr, method); result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(element, arguments); if (result !== false) { loading.show(duration); } return result; }, complete: function (xhr,status) { loading.hide(duration); getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(element, arguments); }, success: function (data, status, xhr) { asyncOnSuccess(element, data, xhr.getResponseHeader("Content-Type") || "text/html"); getFunction(element.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(element, arguments); }, error: function () { getFunction(element.getAttribute("data-ajax-failure"), ["xhr", "status", "error"]).apply(element, arguments); } });
我們看到jquery.unobtrusive-ajax注冊了ajax請求的compelete事件,因此我們寫的默認處理程序就被覆蓋啦。實在沒想到什麼好辦法,只好改下jquery.unobtrusive-ajax的源碼了:
complete: function (xhr,status) { loading.hide(duration); //解析ajax請求session超時問題 var sessionStatus = xhr.getResponseHeader("sessionstatus"); if (sessionStatus === "timeout") { window.location = "/Login/Login"; } getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(element, arguments); },
至此,基於認證的ajax請求session失效問題基本解決,存在兩個瑕疵:
•修改了jquery.unobtrusive-ajax的源碼,總感覺心裡別扭;
•任何注冊了compelete事件的ajax請求,都需要自己處理session問題。
4.無權限任務的Action
無權限認證的Action的Session失效問題,處理代碼如下:
if (filterContext.HttpContext.Session != null) { if (filterContext.HttpContext.Session.IsNewSession) { var sessionCookie = filterContext.HttpContext.Request.Headers["Cookie"]; if (sessionCookie != null&&sessionCookie.IndexOf("ASP_NET_SessionId",StringComparison.OrdinalIgnoreCase)>=0) { filterContext.Result = new RedirectToRouteResult( new RouteValueDictionary(new { Controller = "Login", Action = "Login" })); } } }
無權限認證的Action的Ajax可以仿照上面有權限認證的處理方法處理,這裡就不再粘代碼啦。個人感覺,無權限認證的Action請求,大多可以不用考慮session失效情況,因為這些Action大多不從session裡獲取信息,只是做公共信息的查詢。
5.遺留問題
至此問題基本解決,但是過程中遇到了一個莫名其妙的問題,暫且記下:
我原本通過在配置文件把session超期時間設置的很小來模擬session失效,結果發現項目現有框架總會莫名奇妙的在登錄後的第一個業務請請求時把session超期時間改為60分鐘,沒有找到為什麼。後來只能通過在同一個浏覽器打開兩個tab頁,登錄系統後,在一個tab頁推出的方法模擬。
以上所述是小編給大家介紹的.net mvc session失效問題,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網站的支持!