zoukankan      html  css  js  c++  java
  • MVC过滤器详解

    APS.NET MVC中(以下简称“MVC”)的每一个请求,都会分配给相应的控制器和对应的行为方法去处理,而在这些处理的前前后后如果想再加一些额外的逻辑处理。这时候就用到了过滤器。

     MVC支持的过滤器类型有四种,分别是:Authorization(授权),Action(行为),Result(结果)和Exception(异常)。如下表,

    过滤器类型

    接口

    描述

    Authorization

    IAuthorizationFilter

    此类型(或过滤器)用于限制进入控制器或控制器的某个行为方法

    Exception

    IExceptionFilter

    用于指定一个行为,这个被指定的行为处理某个行为方法或某个控制器里面抛出的异常

    Action

    IActionFilter

    用于进入行为之前或之后的处理

    Result

    IResultFilter

    用于返回结果的之前或之后的处理

      但是默认实现它们的过滤器只有三种,分别是Authorize(授权),ActionFilter,HandleError(错误处理);各种信息如下表所示

    过滤器

    类名

    实现接口

    描述

    ActionFilter

    AuthorizeAttribute

    IAuthorizationFilter

    此类型(或过滤器)用于限制进入控制器或控制器的某个行为方法

    HandleError

    HandleErrorAttribute

    IExceptionFilter

    用于指定一个行为,这个被指定的行为处理某个行为方法或某个控制器里面抛出的异常

    自定义

    ActionFilterAttribute

    IActionFilter和IResultFilter

    用于进入行为之前或之后的处理或返回结果的之前或之后的处理

      下面介绍的过滤器中,除了上面这几种外,还多加一种过滤器OutputCache

    1           授权过滤器Authorize

    1.1          默认Authorize使用

      现在在网上无论是要求身份验证的地方多得是,发邮件,买东西,有时候就算吐个槽都要提示登录的。这里的某些操作,就是要经过验证授权才被允许。在MVC中可以利用Authorize来实现。例如一个简单的修改密码操作

    [Authorize]
            public ActionResult ChangePassword()
            {
                return View();
            }

    它需要用户通过了授权才能进入到这个行为方法里面,否则硬去请求那个页面的话,只会得到这个结果

    如果要通过验证,通过调用FormsAuthentication.SetAuthCookie方法来获得授权,登陆的页面如下

    @model FilterTest.Models.LogInModel
    @{
        Layout = null;
    }
    
    <!DOCTYPE html>
    
    <html>
    <head>
        <title>Login</title>
    </head>
    <body>
        <div>
        @using( Html.BeginForm()){
           <div>
            ID:@Html.TextBoxFor(m=>m.UserName)
            <br />
            Password:@Html.PasswordFor(m => m.Password)
            <br />
            <input type="submit" value="login" />
           </div>
        }
        </div>
    </body>
    </html>
     [HttpPost]//这里用了谓词过滤器,只处理POST的请求
            public ActionResult Login(LogInModel login)
            {
                if (login.UserName == "admin" && login.Password == "123456")
                {
                    FormsAuthentication.SetAuthCookie(login.UserName, false);
                    return Redirect("/Customer/ChangePassword");
                }
    
                return View();
            }

    当然有登录也要有注销,因为注销是在登陆之后发生的,没登陆成功也就没有注销,所以注销的行为方法也要加上Authorize过滤器,注销调用的是FormsAuthentication.SignOut方法,代码如下

     [Authorize]
            public ActionResult LogOut()
            {
                FormsAuthentication.SignOut();
                return Redirect("/Customer/Login");
            }

    1.2          自定义授权

    我们不一定要用MVC默认的Authorize授权验证规则,规则可以自己来定,自定义授权过滤器可以继承AuthorizeAttribute这个类,这个类里面有两个方法是要重写的

    •          bool AuthorizeCore(HttpContextBase httpContext):这里主要是授权验证的逻辑处理,返回true的则是通过授权,返回了false则不是。
    •          void HandleUnauthorizedRequest(AuthorizationContext filterContext):这个方法是处理授权失败的事情。

    这里就定义了一个比较骑呢的授权处理器,当请求的时候刚好是偶数分钟的,就通过可以获得授权,反之则不通过。当授权失败的时候,就会跳转到登陆页面了。

     public class MyAuthorizeAttribute:AuthorizeAttribute
        {
            
            protected override bool AuthorizeCore(HttpContextBase httpContext)
            {
                //return base.AuthorizeCore(httpContext);
                return DateTime.Now.Minute % 2 == 0
            }
    
            
            protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
            {
                filterContext.HttpContext.Response.Redirect("/Customer/Login");
                
                //base.HandleUnauthorizedRequest(filterContext);
            }
        }
     [MyAuthorize]
            public ActionResult ShowDetail()
            {
                return View();
            }

     自定义过滤器:

    控制器代码:

    [CheckLogin]  //此处为自定义属性,要引用相应的命名空间
    public ActionResult Index()
    {
      return View();
    }
    
    public ActionResult Login()   //此Action自动往cookie里写入登录信息
    {
      HttpCookie hcUserName = new HttpCookie("username","admin");
      HttpCookie hcPassWord = new HttpCookie("password","123456");
      System.Web.HttpContext.Current.Response.SetCookie(hcUserName);
      System.Web.HttpContext.Current.Response.SetCookie(hcPassWord);
      return View();
    }

    过滤器代码:

    public class CheckLogin : ActionFilterAttribute
      {
        //在Action执行之前 乱了点,其实只是判断Cookie用户名密码正不正确而已而已。
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
          HttpCookieCollection CookieCollect = System.Web.HttpContext.Current.Request.Cookies;if (CookieCollect["username"] == null || CookieCollect["password"] == null)
          {
            filterContext.Result = new RedirectResult("/Home/Login");
          }
          else
          {
            if (CookieCollect["username"].Value != "admin" && CookieCollect["password"].Value != "123456")
            {
              filterContext.Result = new RedirectResult("/Home/Login");
            }
          }
        }
      }

    此过滤器实现的效果是,当用户Cookie中用户名和密码不正确则跳转到登录页,注意 过 滤器也可以放在整个Controller类的顶部,表示该Controller下的所有Action都执行该项检查。 这样一来,控制器里的代码非常漂亮,再也不用所有的Action里都充斥着判断登录的代码了。

    全局过滤器

    有时 我们想有些公共的方法需要 每个Action都执行,但是又不想再每一个Controller上都打上Action标签,怎么办?幸好Asp。Net MVC3带来了一个美好的东 西,全局Filter。而怎么注册全局Filter呢?答案就在Global.asax中。让我们看以下代码,我是如何将上面我们定义的 TestFilterAttribute 注册到全局Filter中。

     public static void RegisterGlobalFilters(GlobalFilterCollection filters)
            {
                filters.Add(new HandleErrorAttribute());
                //注册全局过滤器
                filters.Add(new TestFilterAttribute() { Message="全局"});
            }

    这样就每个Action都会执行此过滤器,而不必每个Controller顶部都加上标签。

  • 相关阅读:
    如何使界面在较大的屏幕上居中,并且在设计期可以按期望的界面尺寸进行设计?
    Embedding programmatic skins in CSS and compiling to SWF
    将应用程序11M内存占用,降至500K左右
    [转载]FCKeditor添加自定义按钮
    fieldset标签的使用
    转贴
    面向对象的好处
    61条面向对象设计的经验原则
    用 Git 操作的数据库?这个项目火了!
    千万别强制停机!我嘴都气歪了!
  • 原文地址:https://www.cnblogs.com/wuxl360/p/5435983.html
Copyright © 2011-2022 走看看