• ASP.NET MVC--过滤器


    过滤器

    AOP(面向切面编程)是一种架构思想,用于把公共的逻辑放到一个单独的地方,这样就不用每个地方都写重复的代码了。比如程序中发生异常,不用每个地方都try…catch…只要在(Global 的Application_Error)中统一进行异常处理。不用每个Action中都检查当前用户是否有执行权限,

    ASP.net MVC中提供了一个机制,每个Action执行之前都会执行我们的代码,这样统一检查即可。这就是过滤器的原理。

    四个Filter(过滤器)

    在ASP.Net MVC中提供了四个Filter(过滤器)接口实现了这种AOP机制:
    IAuthorizationFilter、IActionFilter、IResultFilter、IExceptionFilter。

    1,IAuthorizationFilter
    一般用来检查当前用户是否有Action的执行权限,在每个Action被执行前执行OnAuthorization方法;

    2,IActionFilter
    也是在每个Action被执行前执行OnActionExecuting方法,每个Action执行完成后执行OnActionExecuted方法和IAuthorizationFilter的区别是IAuthorizationFilter在IActionFilter之前执行,检查权限一般写到IAuthorizationFilter中;

    3,IResultFilter,在每个ActionResult的前后执行IResultFilter。用的很少,后面有一个应用。

    4,IExceptionFilter,当Action执行发生未处理异常的时候执行OnException方法。
    在ASP.net MVC 中仍然可以使用“Global 的Application_Error”,但是建议用IExceptionFilter。

    执行顺序

    如果某个Action过滤器运用了多种过滤器,那么过滤器的执行顺序是如何呢?
    在这里插入图片描述
    即执行顺序是:授权过滤器->动作过滤器->结果过滤器->异常过滤器。

    注意:如果ActionFilter过滤器执行过程中发生了异常,那么会执行ExceptionFilter过滤器,不会执行ResultFilter过滤器。上图所示的是正常情况下的执行顺序。

    授权过滤器

    编写一个类CheckAuthorFilter,实现IAuthorizationFilter接口(需要引用System.Web.Mvc程序集)

    public class CheckLoginFilter : IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationContext filterContext)
        {
            string ctrlName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
            string actionName = filterContext.ActionDescriptor.ActionName;
            if (ctrlName == "Login" && (actionName == "Index" || actionName == "Login"))
            {
                //什么都不做
            }
            else
            {
                if (filterContext.HttpContext.Session["username"] == null)
                {
                    ContentResult contentResult = new ContentResult();
                    contentResult.Content = "没有登录";
                    //filterContext.Result = contentResult;
                    filterContext.Result = new RedirectResult("/Login/Index");
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    2.在Globel中注册这个Filter:GlobalFilters.Filters.Add(new CheckAuthorFilter());
    示例代码:

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        RouteConfig.RegisterRoutes(RouteTable.Routes);
    
        GlobalFilters.Filters.Add(new CheckLoginFilter());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3.CheckAuthorFilter中实现OnAuthorization方法。
    filterContext.ActionDescriptor  可以获得Action的信息:
    filterContext.ActionDescriptor.ActionName  获得要执行的Action的名字;
    filterContext.ActionDescriptor.ControllerDescriptor.ControllerName  为要执行的Controller的名字;

    filterContext.ActionDescriptor.ControllerDescriptor.ControllerType  为要执行的Controller的Type;
    filterContext.HttpContext  获得当前请求的HttpContext;
    如果给“filterContext.Result”赋值了,那么就不会再执行要执行的Action,而是以“filterContext.Result”的值作为执行结果(注意如果是执行的filterContext.HttpContext.Response.Redirect(),那么目标Action还会执行的)。

    4,检查当前用户是否登录,
    如果没有登录则filterContext.Result = new ContentResult() { Content = “没有权限” };
    或者filterContext.Result = new RedirectResult(“/Login/Index”);
    最好不要filterContext.HttpContext.Response.Redirect(“/Login/Index”);)

    异常过滤器

    public class ExceptionFilter : IExceptionFilter
    {
        public void OnException(ExceptionContext filterContext)
        {
            File.AppendAllText("d:/error.log", filterContext.Exception.ToString());
            filterContext.ExceptionHandled = true;//如果有其他的IExceptionFilter不再执行
            filterContext.Result = new ContentResult() { Content = "error" };
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    然后:

    GlobalFilters.Filters.Add(new ExceptionFilter());
    
    • 1

    总结好处:

    一次编写,其他地方默认就执行了。可以添加多个同一个类型的全局Filter,按照添加的顺序执行。
    (*)非全局Filter:
    只要让实现类继承自FilterAttribute类,然后该实现哪个Filter接口就实现哪个(四个都支持)。不添加到GlobalFilters中,而是把这个自定义Attribute添加到Controller类上这样就只有这个Controller中操作会用到这个Filter。

    如果添加到Action方法上,则只有这个Action执行的时候才会用到这个Filter。

  • 相关阅读:
    网络基础(第一节)
    致敬记者节,合合信息扫描全能王助力新闻工作者构建“随身资料库”
    移植freertos到qemu上运行
    逻辑回归-为什么模型会更加侧重于学习那些数值比较大的列
    宇宙始终处于完美状态
    C语言操作符和关键字
    linux应用之文件读取
    关于sqli-labs-master靶场的SQL注入问题。
    九、Spring Boot 缓存(2)
    1006 Sign In and Sign Out
  • 原文地址:https://blog.csdn.net/huan13479195089/article/details/127137767