AspNet MVC3中过滤器 + 实例
过滤器在请求管线注入额外的逻辑,提供简单优雅的方法实现横切点关注(AOP),例如日志,授权,缓存等应用.通过AOP可以减少在实际的业务逻辑中参杂过多非直接业务逻辑功能的代码,让某个行为或者动作更加专注于自身的功能逻辑,例如统计Action,专注于数据的统计分析而不要关注日志以及调用的身份验证和授权问题.
1.过滤器类型
AspNet MVC中包含三种常用的过滤器分别是:Action(行为过滤器) , Result(结果过滤器) ,Exception(异常过滤器)和Authorization(授权过滤器).
| --------------------------------------------------------------------------------------|
| 过滤器类型 | 对应接口 | 描述 |
-----------------------------------------------------------------------------------------
| Authorization IAuthorizationFilter 用于实现用户验证和对Action的访问授权,例如默认的Authorize过滤器
| Action IActionFilter 用于对Action执行前后的逻辑控制,例如修改参数,返回数据controller
| Result IResultFilter 用于修改视图向浏览器展现的结果,通过对ViewReuslt生成前后逻辑控制
| Exception IExceptionFilter 用于处理行为和结果的错误,日志的记录
过滤器的默认执行顺序为Authorization > Action > Result > Exception ,如果需要修改只执行的顺序可以通过修改Order属性来实现.
2. AspNet MVC提供的集中默认过滤器
a. Authorize 用户当前用户登录验证,通过匹配用户名和角色(roles)实现
b. ChildActionOnly 指定当前行为(Action)是某个请求的一部分。
c. OutputCache 控制页面数据的缓存
d. HandleError 页面访问的异常/错误处理,在页面或者行为数据错位时候可以导航到指定的错误页面
3.定制过滤器
用户定制过滤器主要需要实现或者重写一些方法比如:
-
OnAuthorization 身份验证/访问授权
-
OnException 异常错误处理
-
OnActionExecuting 调用Action前
-
OnActionExecuted 调用Action后
-
OnResultExecuting 生成ViewResult前
-
OnResultExecuted 生成ViewResult后
实现途径有两种方式: 一种是通过继承ActionFilterAttribute或者AuthorizeFilterAttribute等类,然后重写对应的逻辑方法,还有一种就是如1中描述的,通过实现一些类似IActionFilter或者ResultFilter等接口来实现,第二种实现相对来说较底层.
例如要实现多某个行为Action的拦截,可以通过继承IActionFilter或者ActionFilterAttribute实现方法OnActionExecuting和OnActionExecuted在请求访问到达指定的Action前对请求进行处理和对访问后返回数据的处理
4.过滤器应用
这里主要演示对Action行为的拦截,一个是针对Action参数的拦截,判断访问请求数据是否包含敏感字眼一个通过action的身份授权验证
如果要直接在行为Action上使用类似属性那般在继承对应的接口时候还要继承类FilterAttribute
a. 敏感字眼的过滤
主要实现OnActionExecuting方法,在请求达到action前先对请求的参数进行过滤,通过指定的过滤算法将参数信息进行过滤替换
public class CustomActionFilterAttribute : IActionFilter { public void OnActionExecuted(ActionExecutedContext filterContext) { } public void OnActionExecuting(ActionExecutingContext filterContext) { //对参数的过滤,例如处理一些比较敏感的信息 //s1: 获取参数信息 ,得到参数的个数以及每个参数的类别 filterContext.ActionDescriptor.GetParameters(); //s2: 获取参数值,返回一个字典 //parameterValue 参数值 , parameterName 参数名 var parameterValue = filterContext.ActionParameters[parameterName]; //s3: 敏感信息过滤 // 过滤算法 // 过滤后赋值 filterContext.ActionParameters[parameterName] = newParameterValue; } }
b. 访问授权
public class AuthenticationFilterAttribute:IActionFilter{ public void OnActionExecuted(ActionExecutedContext filterContext) { //throw new NotImplementedException(); } public void OnActionExecuting(ActionExecutingContext filterContext) { // 未认证直接重定向到登录页面,并设置登录成功后的目标URL if (!filterContext.HttpContext.User.Identity.IsAuthenticated) { string redirect_string = filterContext.HttpContext.Request.Url.AbsolutePath; //设置登录成功后转向的URL,格式例如:http://xxx.xxx/login.aspx?ReturnUrl=www.swzsoft.cn string returnUrl = string.Format("?ReturnUrl={0}", redirect_string); //重定向到登录的URL后面的returnUrl参数用于登录通过后的页面跳转 string loginUrl = System.Web.Security.FormsAuthentication.LoginUrl + returnUrl; filterContext.HttpContext.Response.Redirect(loginUrl, true); } } }
基于角色的访问授权
public class BaseOnRolesAuthenticationFilterAttribute:FilterAttribute, IActionFilter{ public void OnActionExecuted(ActionExecutedContext filterContext) { //throw new NotImplementedException(); } public string Role{get;set;} public BaseOnRolesAuthenticationFilterAttribute(string role){ Role = role; } public void OnActionExecuting(ActionExecutingContext filterContext) { if (!string.IsNullOrEmpty(Role)) { // 未认证直接重定向到登录页面,并设置登录成功后的目标URL if (!filterContext.HttpContext.User.Identity.IsAuthenticated) { string redirect_string = filterContext.HttpContext.Request.Url.AbsolutePath; //设置登录成功后转向的URL,格式例如:http://xxx.xxx/login.aspx?ReturnUrl=www.swzsoft.cn string returnUrl = string.Format("?ReturnUrl={0}", redirect_string); //重定向到登录的URL后面的returnUrl参数用于登录通过后的页面跳转 string loginUrl = System.Web.Security.FormsAuthentication.LoginUrl + returnUrl; filterContext.HttpContext.Response.Redirect(loginUrl, true); } else { bool bIsAuthorized = filterContext.HttpContext.User.IsInRole(this.Role); if (!bIsAuthorized) { throw new UnauthorizedAccessException(""); } } }else{ throw new InvalidOperationException(""); } } } // 应用,针对某个Controller的某个Action [BaseOnRolesAuthenticationFilter("Andy")] public ActionResult AdminIndex() { ViewBag.Msg = "Amdin INdex"; return View(); }