MVC过滤器之添加LoginAttribute,浏览器提示:重定向次数太多

      以前在写登录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     }

 

posted @ 2017-06-28 17:54  jerliu  阅读(2339)  评论(7编辑  收藏  举报