以前在寫登錄Action過濾時,都在每個Controller前寫上CheckLoginAttribute;這次決定偷懶試一下能否將所有Action和Controller統一過濾;
開始代碼是這樣式兒的:
1.新建一個特性類,繼承ActionFilterAttribute,在Action執行前判斷是否有登錄記錄Session,則在OnActionExecuting(ActionExecutingContext filterContext)中判斷未登錄,則返回登錄界面;
1 public class LoginAttribute:ActionFilterAttribute 2 { 3 4 public override void OnActionExecuting(ActionExecutingContext filterContext) 5 { 6 base.OnActionExecuting(filterContext); 7 8 if (filterContext.HttpContext.Session["useruid"] == null) 9 { 10 filterContext.Result = new RedirectResult("/Home/Login"); 11 return; 12 } 13 14 } 15 }
2.在App_Start文件夾里的FilterConfig.cs,添加LoginAttribute
1 public class FilterConfig 2 { 3 public static void RegisterGlobalFilters(GlobalFilterCollection filters) 4 { 5 filters.Add(new HandleErrorAttribute()); 6 filters.Add(new LoginAttribute());//新增登錄特性 7 } 8 }
運行后,網頁如下圖,清除cookie完全無效。

查找問題原因:單步調試后,發現RegisterGlobalFilters中的filters.Add(new LoginAttribute()) 和 LoginAttribute中的RedirectResult,都會執行多次,次數和什么有關呢?
在運行到LoginAttribute前,曾經在定義Controller的依賴注入UnityContainer里晃了一圈,重復執行RedirectResult的次數和容器注入的類數有關,先執行到依賴注入再執行到OnActionExecuting,應該是在Action操作之前,先對所有Controller依賴構造器接口進行初始化操作,初始化操作涉及到各個Controller。
再看RegisterGlobalFilters初始化是屬於Global.asax.cs,用於對全局文件配置的,在每執行一次Controller中的Action,都會執行一次LoginAttribute。於是初始化所有Controller依賴注入接口期間,有觸發LoginAttribute。RouteConfig配置Home\Login為默認啟動Action。所以,在啟動Home\Login后,在初始化Controller的依賴注入后會連續多次執行RedirectResult(“/Home/Login“”),導致程序並沒報錯,而瀏覽器崩潰。
於是這樣改了試試:
1 public override void OnActionExecuting(ActionExecutingContext filterContext) 2 { 3 base.OnActionExecuting(filterContext); 4 5 //增加對初始化/Home/Login判定,直接跳出,避免多次執行RedirectResult 6 string url = filterContext.HttpContext.Request.Url.ToString(); 7 if (url.IndexOf("Home") > 0&&url.IndexOf("Login")>0) 8 { 9 return; 10 } 11 //增加部分到此結束 12 13 if (filterContext.HttpContext.Session["useruid"] == null) 14 { 15 filterContext.Result = new RedirectResult("/Home/Login"); 16 return; 17 } 18 }
然后暫時解決了。在各位大神幫忙指正下,添加標簽的方式然后根據標簽判斷,比判斷關鍵字符串,更便於擴展維護。
最后代碼如下:
1 public class LoginAttribute:ActionFilterAttribute 2 { 3 4 public override void OnActionExecuting(ActionExecutingContext filterContext) 5 { 6 //判斷Action描述標簽中是否有AllowAnonymous特性 7 if(filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true)) 8 { 9 return; 10 } 11 12 if (filterContext.HttpContext.Session["useruid"] == null) 13 { 14 filterContext.Result = new RedirectResult("/Home/Login"); 15 return; 16 } 17 base.OnActionExecuting(filterContext); 18 19 } 20 }
