• APS.NET MVC + EF (11)---过滤器


    过滤器本质就是对动作方法的执行过程进行干预,这种干预可以影响动作方法执行的各个过程。ASP.NET MVC 提供了4种类型的接口,并在接口中定义了各种成员,代表代码执行的各个阶段,这些接口和成员如表11-1所示。

    表11-1 常见过滤器接口

    过滤器类型

    接口

    默认实现

    描述

    Action

    IActionFilter

    ActionFilterAttribute

    在动作方法之前及之后运行

    Result

    IResultFilter

    ActionFilterAttribute

    在动作结果被执行之前和之后运行

    AuthorizationFilter

    IAuthorizationFilter

    AuthorizeAttribute

    首先运行,在任何其它过滤器或动作方法之前

    Execption

    IExceptionFilter

    HandleErrorAttribute

    只在另一个过滤器、动作方法、动作结果弹出异常时运行

       

    当动作方法同时应用了继承自这些特性的过滤器后,实际的执行过程如图11-1所示。

       

    图11-1 过滤器执行过程

       

    图11-1中流程并没有列出 OnException() 方法的执行时机,事实上,在执行流程中只要任何环节出现异常,就会执行 OnException()方法。

    11.1 过滤器的使用

    ASP.NET MVC 的这种过滤器机制,实际是体现了一种 AOP(面向切面) 设计思想,当需要为动作方法进行干预时,不需要变动动作方法内部的代码,就可以扩张横向的行为。在实际开发中,只需要继承这些接口,实现自定义的特性,并在动作方法上应用自定义的特性,就可以扩展动作方法的能力。实现自定义的过滤器特性,需要满足两个要求。一是实现表11-1中任意的接口,二是继承FilterAttribute,标识它是一个过滤器。接下来介绍自定义过滤器的用法。

       

    11.1.1 Action 过滤器

    在ASP.NET MVC 项目中创建文件夹Filter,然后新建类MyActionFilterAttribute(为了遵循默认的约定,名称以Attribute结尾),继承自ActionFilterAttribute类。ActionFilterAttribute类有如下4个方法。

    public virtual void OnActionExecuted(ActionExecutedContext filterContext);

    public virtual void OnActionExecuting(ActionExecutingContext filterContext);

    public virtual void OnResultExecuted(ResultExecutedContext filterContext);

    public virtual void OnResultExecuting(ResultExecutingContext filterContext);

    MyActionFilterAttribute.cs 类的代码如示例1所示。

    示例1

    public class MyActionFilterAttribute : ActionFilterAttribute

    {

    //Action执行之前

    public override void OnActionExecuting(ActionExecutingContext filterContext)

    {

    //1、获取请求的类名和方法名

    string strController = filterContext.RouteData.Values["controller"].ToString();

    string strAction = filterContext.RouteData.Values["action"].ToString();

       

    //2、用另一种方式获取请求的类名和方法名

    string strController2 = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;

    string strAction2 = filterContext.ActionDescriptor.ActionName;

       

    filterContext.HttpContext.Response.Write("控制器:" + strController + "<br/>");

    filterContext.HttpContext.Response.Write("控制器:" + strController2 + "<br/>");

    filterContext.HttpContext.Response.Write("Action:" + strAction + "<br/>");

    filterContext.HttpContext.Response.Write("Action:" + strAction2 + "<br/>");

    filterContext.HttpContext.Response.Write("Action执行前:" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + "<br/>");

    base.OnActionExecuting(filterContext);

       

    }

    //Action执行之后

    public override void OnActionExecuted(ActionExecutedContext filterContext)

    {

    filterContext.HttpContext.Response.Write("Action执行后:" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + "<br/>");

    base.OnActionExecuted(filterContext);

    }

    }

    对于过滤器,我们可以把它们加在3个地方,一个是控制器上面(控制器下面的所有Action),一个是Action上面(指定标识的Action),另一个就是全局位置(所有控制器中的Action)

    在控制器上代码如下:

    [MyActionFilter]

    public ActionResult Index()

    {

    return View();

    }

    11.1.2 Result 过滤器

    在Filter文件夹中新建MyResultFilterAttribute类,继承ActionFilterAttribute。如示例2所示。

    示例2

    public class MyResultAttribute: ActionFilterAttribute

    {

    // 加载"视图"前执行

    public override void OnResultExecuting(ResultExecutingContext filterContext)

    {

    filterContext.HttpContext.Response.Write("加载视图前执行 OnResultExecuting" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + "<br/>");

    base.OnResultExecuting(filterContext);

    }

    // 加载"视图"后执行

    public override void OnResultExecuted(ResultExecutedContext filterContext)

    {

    filterContext.HttpContext.Response.Write("加载视图后执行 OnResultExecuted" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + "<br/>");

    base.OnResultExecuted(filterContext);

    }

    }

    这里把MyResultFilter过滤器加在控制器上面,相当于给Home控制器中的所有的Action方法添加了MyResultFilter过滤器。如下代码所示。

    [MyResultFilter]

    public class HomeController : Controller

    {

    [MyActionFilter]

    public ActionResult Index()

    {

    return View();

    }

    }

       

    11.1.3 AuthorizeAttribute过滤器

    创建MyAuthorizeAttribute类,继承AuthorizeAttribute类。如示例3所示。

    示例3

    public class MyAuthorizeAttribute: AuthorizeAttribute

    {

    public override void OnAuthorization(AuthorizationContext filterContext)

    {

    filterContext.HttpContext.Response.Write("OnAuthorization<br/>");

    //注释掉父类方法,

    //因为父类里的OnAuthorization方法会调用ASP.NET的授权验证机制

    //base.OnAuthorization(filterContext);

    }

    }

    在控制器Home中的Index上添加MyAuthorize过滤器。

    [MyActionFilter]

    [MyAuthorize]

    public ActionResult Index()

    {

    return View();

    }

    通常Authorize过滤器也是在全局过滤器上面的,主要用来做登录验证或者权限验证,在App_Start目录下的FilterConfig类的RegisterGlobalFilters方法中添加:

    public class FilterConfig

    {

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)

    {

    filters.Add(new HandleErrorAttribute());

    //添加全局授权过滤器

    filters.Add(new MyAuthorizeAttribute());

    }

    }

    在全局中注册过滤器,则所有控制器的所有行为(Action)都会执行这个过滤器。

       

    11.1.4 Exception过滤器

    创建MyHandleErrorAttribute类,继承HandleErrorAttribute类。如示例4所示。

    示例4

    public class MyHandleErrorAttribute: HandleErrorAttribute

    {

    public override void OnException(ExceptionContext filterContext)

    {

    //1、获取异常对象

    Exception ex = filterContext.Exception;

    //2、记录异常日志 (将错误信息利用IO保存到文件)

    //3、重定向友好页面

    filterContext.Result = new RedirectResult("~/error.html");

    //4、标记异常已经处理完毕

    filterContext.ExceptionHandled = true;

    base.OnException(filterContext);

    }

    }

    在Action上面添加MyHandleError过滤器,如下所示。

    [MyHandleError]

    public ActionResult GetErr()

    {

    int a = 0;

    int b = 1 / a;

    return View();

    }

    运行会自动跳转到error.html页面。

    如果页面没有跳转,就需要去Web.config配置文件中的<system.web>节点下面添加如下配置节点,开启自定义错误:

    <customErrors mode="On"></customErrors>

       

    通常这样的异常处理是放在全局过滤器上面的,只要任意Action方法报错就会执行MyHandleError过滤器中的代码。

    修改App_Start目录下面的FilterConfig类:

    public class FilterConfig

    {

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)

    {

    //添加全局授权过滤器

    filters.Add(new MyAuthorizeAttribute());

    //添加全局异常处理过滤器

    filters.Add(new MyHandleErrorAttribute());

    }

    }

    Global.asax下的代码:

    public class MvcApplication : System.Web.HttpApplication

    {

    protected void Application_Start()

    {

    App_Start.AutoMapperConfig.Config();

       

    AreaRegistration.RegisterAllAreas();

    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

    RouteConfig.RegisterRoutes(RouteTable.Routes);

    BundleConfig.RegisterBundles(BundleTable.Bundles);

    }

    }

       

    11.2 基于Form的身份验证

       

    身份验证流程

    一、用户登录

      1、验证表单:ModelState.IsValid

      2、验证用户名和密码:通过查询数据库验证

      3、如果用户名和密码正确,则在客户端保存Cookie以保存用户登录状态:SetAuthCookie

        1):从数据库中查出用户名和一些必要的信息,并把额外信息保存到UserData中

        2):把用户名和UserData保存到 FormsAuthenticationTicket 票据中

        3):对票据进行加密 Encrypt

        4):将加密后的票据保存到Cookie发送到客户端

      4、跳转到登录前的页面

    二、验证登录

      1、在Global中注册PostAuthenticateRequest事件函数,用于解析客户端发过来的Cookie数据

        1):通过 HttpContext.Current.User.Identity 判断用户是否登录(FormsIdentity,IsAuthenticated,AuthenticationType)

        2):从HttpContext 的Request的Cookie中解析出Value,解密得到 FormsAuthenticationTicket 得到UserData

      2、角色验证

        在Action加入 Authorize特性,可以进行角色验证

        在 HttpContext.Current.User 的 IsInRole 方法进行角色认证(需要重写)

       

       

       

       

       

  • 相关阅读:
    Python爬虫基础——re模块的提取、匹配和替换
    Python爬虫基础——正则表达式
    Python爬虫基础——HTML、CSS、JavaScript、JQuery网页前端技术
    Python——面向对象(类)的基础疑难点
    简单易懂的ftp脚本自动登录教程
    如何完成述职报告或年终总结PPT
    nmon脚本——对Linux服务器的监控
    记——第一次服务器被挖矿
    vsftpd超实用技巧详解
    MySQL、Oracle、SqlServer的区别
  • 原文地址:https://www.cnblogs.com/mrfang/p/10868448.html
Copyright © 2020-2023  润新知