ASP.NET MVC之Filter学习

 

前言

Filter(筛选器)是一种AOP式的设计,学会了Filter我们能很方便的对权限管理、防盗链、防蜘蛛的管理。

在MVC中提供了四种类型的Filter,分别是Authorization、Action、Result、Exception

11225919-d945fcabe763410a8303810573863fff

从上图中可以看出各个Filter实现的顺序,当然我们可以手动的去自定义一个Filter类去实现其中的逻辑代码

现在我们来做一个简单的demo例子

ActionFilterAttribute

abstract ActionFilterAttribute实现了IActionFilter,IResultFilter接口,通过重写ActionFilterAttribute我们可以自定Action在持行前后和view视图显示前后的逻辑代码

// 摘要:
    //     表示筛选器特性的基类。
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
    public abstract class ActionFilterAttribute : FilterAttribute, IActionFilter, IResultFilter
    {
        // 摘要:
        //     初始化 System.Web.Mvc.ActionFilterAttribute 类的新实例。
        protected ActionFilterAttribute();

        // 摘要:
        //     在执行操作方法后由 ASP.NET MVC 框架调用。
        //
        // 参数:
        //   filterContext:
        //     筛选器上下文。
        public virtual void OnActionExecuted(ActionExecutedContext filterContext);
        //
        // 摘要:
        //     在执行操作方法之前由 ASP.NET MVC 框架调用。
        //
        // 参数:
        //   filterContext:
        //     筛选器上下文。
        public virtual void OnActionExecuting(ActionExecutingContext filterContext);
        //
        // 摘要:
        //     在执行操作结果后由 ASP.NET MVC 框架调用。
        //
        // 参数:
        //   filterContext:
        //     筛选器上下文。
        public virtual void OnResultExecuted(ResultExecutedContext filterContext);
        //
        // 摘要:
        //     在执行操作结果之前由 ASP.NET MVC 框架调用。
        //
        // 参数:
        //   filterContext:
        //     筛选器上下文。
        public virtual void OnResultExecuting(ResultExecutingContext filterContext);
    }

自定义的Filer

接下来我们自定义了一个TestActionFilter来重写ActionFilterAttribute

public class TestActionFilter : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            filterContext.HttpContext.Response.Write("方法名称:FOnActionExecuting<br/>");
            //base.OnActionExecuting(filterContext);
        }

        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            filterContext.HttpContext.Response.Write("方法名称:OnActionExecuted<br/>");
            //base.OnActionExecuted(filterContext);
        }

        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            filterContext.HttpContext.Response.Write("方法名称:OnResultExecuting<br/>");
           // base.OnResultExecuting(filterContext);
        }

        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            filterContext.HttpContext.Response.Write("方法名称:OnResultExecuted<br/>");
            //base.OnResultExecuted(filterContext);
        }
    }

在控制器中给Action定义了一个TestActionFilter

public class TestController : Controller
    {
        //
        // GET: /Test/

        [TestActionFilter]
        public ActionResult Index()
        {
            return View();
        }

    }

运行可以得到

image

可以重图中看到,持行的方法是其分别持行的先后顺序

AuthorizeAttribute

   同样AuthorizeAttribute实现IAuthorizationFilter接口,其持行顺序是在所有的Filter持行之前

    我们在刚才实现的TestActionFilter中实现IAuthorizationFilter接口

public class TestActionFilter : ActionFilterAttribute,IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationContext filterContext)
        {
            filterContext.HttpContext.Response.Write("方法名称:OnAuthorization<br/>");
        }

//....
}

运行后在view视图中可以看到

image 

HandleErrorAttribute

   同理HandleErrorAttribute实现的是IExceptionFilter

   继续上面一样的操作,我们可以看到

public void OnException(ExceptionContext filterContext)
        {
            filterContext.HttpContext.Response.Write("方法名称:OnException<br/>");
        }

Exception Filter,在下面三种来源抛出未处理的异常时运行:1.其他的fiter运行错误(如Authorization、Action或者Result等filter)2.Action方法本身报错3.Action方法持行完成(即处理ActionResult的时候)

禁用异常跟踪

     很多时候异常是不可预料的,在每个Action方法或Controller上应用Exception Filter是不现实的。而且如果异常出现在View中也无法应用Filter。我们可以通过配置Web.config让应用程序不管在何时何地引发了异常都可以显示统一的友好错误信息。在Web.config文件中的<system.web>节点下添加如下子节点:

<system.web>
    <customErrors mode="On" defaultRedirect="/Content/ErrorPage.html"/>
  </system.web>

使用AuthorizeAttribute来进行权限管理

重写AuthorizeAttribute中的AuthorizeCore方法来判断用户的授权请求

public string Users { get; set; }
public string Roles { get; set; }

User属性是获取用户或者设置授权用户

Role属性是获取或设置用户角色

通过重写AuthorizeAttribute的HandleUnauthorizedRequest方法来处理未通过的请求

用户验证登陆

public ActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Index(string username, string password)
        {
            testEntities DbContext = new testEntities();
            var query = from user in DbContext.Users
                        where user.UserName == username && user.UserPwd == password
                        select user;
            if (query.Count() == 0)
            {
                return Content("用户名密码不正确");
            }
            else
            {
                Session["username"] = username;
                Session["password"] = password;
                Session["User"] = "admin";
                return RedirectToAction("tiaozhuanquanxian");
            }
        }

跳转的action“tiaozhuanquanxian”,我们做权限控制,限制其属于roles的“admin”下的user角色“aaaa”可以访问此控制器

public ActionResult tiaozhuan4no()
        {
            return View();
        }

        [Class1(Users="aaaa",Roles="admin")]
        public ActionResult tiaozhuanquanxian()
        {
            return View();
        }

Class1Attribute的代码

public class Class1Attribute  :AuthorizeAttribute
    {
        

        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {

            string user = httpContext.Session["username"].ToString();
            string Role = httpContext.Session["User"].ToString();
            if (Role == Roles && user == Users)
            {
              
                 //new RedirectResult("../Login/tiaozhuang");
                return true;
            }
           
            return false;

           // return this.Allowed;
           // return base.AuthorizeCore(httpContext);
        }

        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {

            filterContext.Result = new RedirectResult("../Login/tiaozhuan4no");
           // base.HandleUnauthorizedRequest(filterContext);
        }
        
    }
}

注册为全局的Filter

我们现在已经基本了解了如何使用上面四种Filter,当我们给某个Contoller或着某个Action添加自定义的Filter的时候,我们都是以标签的形式在上边标注

[Class1(Users="aaaa",Roles="admin")]
        public ActionResult tiaozhuanquanxian()
        {
            return View();
        }

但是现在如果我们要给应用程序下的所有Controller和Action注册Filter,我们是不可能每个都手动调节类似于的标签

[Class1(Users="aaaa",Roles="admin")]

在App_Start/FilterConfig.cs文件中的RegisterGlobalFilters方法,可以把一个Filter类注册为全局,如:

public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
            filters.Add(new TestActionFilter());
        }
    }

在此我们添加了一个全局的TestActionFilter的Filter

image已经成功注册上了

原文地址:https://www.cnblogs.com/ilooking/p/4112906.html