詳解.net mvc session失效問題
最近在研究有關(guān).net mvc項(xiàng)目中的session失效問題,下面小編把研究過程給大家共享下,大家可以參考下。
最近解決基于.net mvc項(xiàng)目的session失效問題,這個(gè)跟大家聊聊。
1.問題分析
.net mvc中,Session失效需要考慮幾種情況:
•基于權(quán)限認(rèn)證的Action,使用非Ajax請(qǐng)求;
•基于權(quán)限認(rèn)證的Action,使用JQueryt Ajax請(qǐng)求;
•基于權(quán)限認(rèn)證的Action,使用.net mvc封裝的Ajax請(qǐng)求;
•無權(quán)限認(rèn)證的Action,使用非Aajx請(qǐng)求;
•無權(quán)限認(rèn)證的Action,使用原生JQuery Ajax請(qǐng)求;
•無權(quán)限認(rèn)證的Action,使用.net mvc封裝的Ajax請(qǐng)求;
基于權(quán)限認(rèn)證的Action,session失效后AuthorizeAttribute都可以攔截,并在HandleUnauthorizedRequest方法中處理;無權(quán)限認(rèn)證的Action需要在自定義的filter中,根據(jù)新建Session與已請(qǐng)求Session的區(qū)別進(jìn)行判斷和處理。
2.基于權(quán)限認(rèn)證的非Ajax請(qǐng)求
Authorize filter優(yōu)先于其他功能過濾器執(zhí)行,因此這里繼承AuthorizeAttribue,在HandleUnauthorizedRequest中處理session請(qǐng)求。
public class AuthorizeOfHandleUnAuthorizeAttribute:AuthorizeAttribute { protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { //session失效重定向到登錄頁面 filterContext.Result = new RedirectToRouteResult( new RouteValueDictionary(new { Controller = "Login", Action = "Login" })); } }
3.基于權(quán)限認(rèn)證的Ajax請(qǐng)求
Ajax請(qǐng)求的Action在系統(tǒng)中存在兩種返回結(jié)果:JsonResult和PartialViewResult。
•JsonResult理論上可以通過在返回的結(jié)果上增加session超期屬性,客戶端進(jìn)行判斷即可。但是考慮到項(xiàng)目已經(jīng)完成,在所有ajax請(qǐng)求上增加判斷邏輯有些繁瑣。
服務(wù)端代碼處理ajax請(qǐng)求:
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { //ajax請(qǐng)求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" })); }
客戶端代碼(這種處理方式對(duì)于返回結(jié)果為PartialViewResult的Action是不適用的):
onSuccess: function (xhr, status) { //獲取響應(yīng)頭,sessionstatus, var sessionstatus = xhr.getResponseHeader("sessionstatus"); if (sessionstatus == "timeout") { window.location = "/Login/Login"; } }
•PartialViewResult情況的存在,直接否定上面的設(shè)想。項(xiàng)目中大部分Ajax請(qǐng)求都是基于.net mvc封裝的,直接更新指定div。
為了不做大量更改、且統(tǒng)一處理兩種返回結(jié)果的ajax請(qǐng)求,找到了另外一種方法
jQuery.ajaxSetup()
該函數(shù)用于更改jQuery中AJAX請(qǐng)求的默認(rèn)設(shè)置選項(xiàng)。之后執(zhí)行的所有AJAX請(qǐng)求,如果對(duì)應(yīng)的選項(xiàng)參數(shù)沒有設(shè)置,將使用更改后的默認(rèn)設(shè)置。
因此我們的客戶端代碼可以這樣統(tǒng)一處理:
//解析ajax請(qǐng)求session超時(shí)問題 $.ajaxSetup({ complete: function(xmlHttpRequest, textStatus) { var sessionStatus = xmlHttpRequest.getResponseHeader("sessionstatus"); if (sessionStatus === "timeout") { window.location = "/Login/Login"; } } });
本以為到這里就萬事大吉啦,結(jié)果一不小心又發(fā)現(xiàn)一個(gè)問題,基于.net mvc的jquery.unobtrusive-ajax封裝的ajax請(qǐng)求調(diào)用,沒有達(dá)到攔截處理的效果。經(jīng)過反復(fù)調(diào)試無果,最終還是注意到上面那段話
jQuery.ajaxSetup()該函數(shù)用于更改jQuery中AJAX請(qǐng)求的默認(rèn)設(shè)置選項(xiàng)。之后執(zhí)行的所有AJAX請(qǐng)求,如果對(duì)應(yīng)的選項(xiàng)參數(shù)沒有設(shè)置,將使用更改后的默認(rèn)設(shè)置。
這里說的比較明白了,那肯定就是jquery.unobtrusive-ajax封裝的時(shí)候搗的鬼啦,翻開源碼一看果然如此:
$.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); } });
我們看到j(luò)query.unobtrusive-ajax注冊(cè)了ajax請(qǐng)求的compelete事件,因此我們寫的默認(rèn)處理程序就被覆蓋啦。實(shí)在沒想到什么好辦法,只好改下jquery.unobtrusive-ajax的源碼了:
complete: function (xhr,status) { loading.hide(duration); //解析ajax請(qǐng)求session超時(shí)問題 var sessionStatus = xhr.getResponseHeader("sessionstatus"); if (sessionStatus === "timeout") { window.location = "/Login/Login"; } getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(element, arguments); },
至此,基于認(rèn)證的ajax請(qǐng)求session失效問題基本解決,存在兩個(gè)瑕疵:
•修改了jquery.unobtrusive-ajax的源碼,總感覺心里別扭;
•任何注冊(cè)了compelete事件的ajax請(qǐng)求,都需要自己處理session問題。
4.無權(quán)限任務(wù)的Action
無權(quán)限認(rèn)證的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" })); } } }
無權(quán)限認(rèn)證的Action的Ajax可以仿照上面有權(quán)限認(rèn)證的處理方法處理,這里就不再粘代碼啦。個(gè)人感覺,無權(quán)限認(rèn)證的Action請(qǐng)求,大多可以不用考慮session失效情況,因?yàn)檫@些Action大多不從session里獲取信息,只是做公共信息的查詢。
5.遺留問題
至此問題基本解決,但是過程中遇到了一個(gè)莫名其妙的問題,暫且記下:
我原本通過在配置文件把session超期時(shí)間設(shè)置的很小來模擬session失效,結(jié)果發(fā)現(xiàn)項(xiàng)目現(xiàn)有框架總會(huì)莫名奇妙的在登錄后的第一個(gè)業(yè)務(wù)請(qǐng)請(qǐng)求時(shí)把session超期時(shí)間改為60分鐘,沒有找到為什么。后來只能通過在同一個(gè)瀏覽器打開兩個(gè)tab頁,登錄系統(tǒng)后,在一個(gè)tab頁推出的方法模擬。
以上所述是小編給大家介紹的.net mvc session失效問題,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
- ASP.NET Session使用詳解
- ASP.NET中在一般處理程序中使用session的簡單介紹
- asp.net(c#)有關(guān) Session 操作的幾個(gè)誤區(qū)
- asp.net BasePage類+Session通用用戶登錄權(quán)限控制
- cookie、session和java過濾器結(jié)合實(shí)現(xiàn)登陸程序
- php中session退出登陸問題
- Jsp中解決session過期跳轉(zhuǎn)到登陸頁面并跳出iframe框架的方法
- 使用PHP會(huì)話(Session)實(shí)現(xiàn)用戶登陸功能
- ASP.NET在IE10中無法判斷用戶已登入及Session丟失問題解決方法
- MVC使用Controller代替Filter完成登錄驗(yàn)證(Session校驗(yàn))學(xué)習(xí)筆記5
相關(guān)文章
asp.net實(shí)現(xiàn)中英文多域名檢測(cè)的方法
這篇文章主要介紹了asp.net實(shí)現(xiàn)中英文多域名檢測(cè)的方法,涉及asp.net針對(duì)URL中域名的解析及字符串操作相關(guān)技巧,需要的朋友可以參考下2016-08-08VS2015自帶LocalDB數(shù)據(jù)庫用法詳解
這篇文章主要為大家詳細(xì)介紹了VS2015自帶LocalDB數(shù)據(jù)庫的用法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06[Asp.Net MVC4]驗(yàn)證用戶登錄實(shí)現(xiàn)實(shí)例
這篇文章主要介紹了[Asp.Net MVC4]驗(yàn)證用戶登錄實(shí)現(xiàn)實(shí)例,這里整理了詳細(xì)的代碼,具有一定的參考價(jià)值,有需要的小伙伴可以參考下。2016-12-12asp.net實(shí)現(xiàn)根據(jù)城市獲取天氣預(yù)報(bào)的方法
這篇文章主要介紹了asp.net實(shí)現(xiàn)根據(jù)城市獲取天氣預(yù)報(bào)的方法,涉及asp.net調(diào)用新浪接口獲取天氣預(yù)報(bào)信息的實(shí)現(xiàn)技巧,非常簡單實(shí)用,需要的朋友可以參考下2015-12-12asp.net自定義控件中注冊(cè)Javascript問題解決方案
這篇文章主要介紹了asp.net自定義控件中注冊(cè)Javascript的問題,需要的朋友可以參考下2014-05-05讀取純真IP數(shù)據(jù)庫的公用組件接口QQWry.NET
這是一個(gè)讀取純真IP數(shù)據(jù)庫的公用組件接口,我是通過luma的《純真IP數(shù)據(jù)庫格式詳解》了解了純真IP數(shù)據(jù)庫數(shù)據(jù)格式,并且基于網(wǎng)絡(luò)上的一個(gè)IPLocation.dll源碼的基礎(chǔ)改編而來2013-06-06