最近比较忙,博客很久没更新了,很多博友问何时更新博文,因此,今天就花了点时间,写了本篇文章,但愿大家喜欢。
本篇文章不适合初学者,需要对ASP.NET MVC具有一定基础。
本篇文章主要从ASP.NET MVC 基架角度去分析MVC框架是如何实现资源过滤,资源授权,感兴趣的,欢迎阅读。
相关文章,请参与ASP.NET MVC系列
一 ASP.NET MVC框架验证机制
为了更加透彻地了解MVC的过滤机制,我简要地画了如下UML图。
下面,我们根据如上的UML图来简要分析一下。
(一)MVC基架过滤机制根接口
根接口:本文指在继承关系中的根节点,相当于类的祖宗对象Object。
从上图中,很容易看出MVC过滤机制的根接口主要有六大类型接口:_Attribute,IMvcFilter,IActionFilter,IResultFilter,IExceptionFilter和IAuthorizationFilter。
1._Attribute
_Attribute接口主要提供一些非托管服务。
2.IMvcFilter
该接口主要用于定义筛选器顺序和是否允许多个筛选器,如当我们给某个action限定多个特性时的执行顺序问题。
[Filter1(Order = 3)][Filter2(Order = 2)][Filter3(Order = 1)]public ActionResult Index(){ ???return View(); ;}
3.IActionFilter
该接口主要定义操作的筛选,在执行操作方法前后,分别调用方法OnActionExecuting(ActionExecutingContext filterContext)和方法OnActionExecuted(ActionExecutedContext filterContext)。IResult也有类似两个方法。
4.IResultFilter
该接口主要用作操作结果的筛选。对于MVC模式开发的程序员来说,ActionResult再熟悉不过了,然而,MVC机制会在操作结果执行前后,分别执行OnResultExecuting(ResultExecutingContext filterContext)方法和OnResultExecuted(ResultExecutedContext filterContext)方法,然后再将最终结果Responce给用户,
5.IExceptionFilter
该接口主要是用来处理系统异常问题,如在项目中经常用到的throw new Exception();
6.IAuthorizationFilter
该接口用来定义资源的筛选和授权,在项目中,主要用做权限管理。
(二) 三个抽象接口
从上图继承图中,不难看出,MVC过滤机制,提供了三个重要的抽象类,分别为:_Attribute,FilterAttribute和ActionFilterAttribute
1.ActionFilterAttribute
从继承图中知道,ActionFilterAttribute继承FilterAttribute抽象类,实现IAcionFilter接口和IResultFilter接口。
反编译代码如下:
不难看出,ActionFilterAttribute共有四个虚方法和一个可被继承构造函数,而四个虚方法,分别是IAcionFilter接口和IResultFilter方法签名的原型。
四个虚方法,在上面我们已经分析过,这里就不分析了,重点分析一下这四个方法的执行顺序:
=》Request ip=>Route(路由器寻找具体Controller和action)=>执行action上面的特性=》OnActionExecutiong=》执行方法=》OnActionExecuted=》OnResultExecuting=》执行操作结果=》OnResultExecuted=》将执行结果最终Responce给浏览器。
源码:
public class ExeOrderTestAttribute:ActionFilterAttribute ???{ ???????public override void OnActionExecuted(ActionExecutedContext filterContext) ???????{ ???????????Log("OnActionExecuted", filterContext.RouteData); ???????????base.OnActionExecuted(filterContext); ???????} ???????public override void OnActionExecuting(ActionExecutingContext filterContext) ???????{ ???????????Log("OnActionExecuting", filterContext.RouteData); ???????????base.OnActionExecuting(filterContext); ???????} ???????public override void OnResultExecuted(ResultExecutedContext filterContext) ???????{ ???????????Log("OnResultExecuted", filterContext.RouteData); ???????????base.OnResultExecuted(filterContext); ???????} ???????public override void OnResultExecuting(ResultExecutingContext filterContext) ???????{ ???????????Log("OnResultExecuting", filterContext.RouteData); ???????????base.OnResultExecuting(filterContext); ???????} ???????private void Log(string methodName, RouteData routeData) ???????{ ???????????var controllerName = routeData.Values["controller"]; ???????????var actionName = routeData.Values["action"]; ???????????var message = String.Format("{0} controller: {1} action: {2}", methodName, controllerName, actionName); ???????????Debug.WriteLine(message, "ASP.NET MVC Filter ExecuteOrder"); ???????} ???}
(三)其他类
从上面的继承图中可以看出,ASP.NET MVC过滤机制,处理定义接口,抽象类外,还有一些其他基础类,比较关键的类有:OutputCacheAttribute,ValidateInpuntAttribute,AuthorizeAttribute和ValidateAntiForgeryTokenAttribute。
1.OutputCacheAttribute
该类主要是解决Cache问题,感兴趣的,可以看看浅谈缓存技术在ASP.NET中的运用 ,这里不累述。
2.ValidateInpuntAttribute 和ValidateAntiForgeryTokenAttribute
主要解决表单验证问题,如防止漏洞注入,JS注入等问题。
3.AuthorizeAttribute
该类主要解决资源授权问题,也就是平时大家所说的权限管等问题,是非常重要的一个类,因此将在本篇文章的第二部分单独讲解。
二 MVC框架授权机制
ASP.NET MVC框架通过AuthorizeAttribute类实现资源的权限控制访问。
我们先来通过反汇编看看AuthorizeAttribute。
?1 [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited=true, AllowMultiple=true)] ?2 public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter ?3 { ?4 ????// Fields ?5 ????private string _roles; ?6 ????private string[] _rolesSplit = new string[0]; ?7 ????private static readonly char[] _splitParameter = new char[] { ‘,‘ }; ?8 ????private readonly object _typeId = new object(); ?9 ????private string _users; 10 ????private string[] _usersSplit = new string[0]; 11 ?12 ????// Methods 13 ????protected virtual bool AuthorizeCore(HttpContextBase httpContext) 14 ????{ 15 ????????if (httpContext == null) 16 ????????{ 17 ????????????throw new ArgumentNullException("httpContext"); 18 ????????} 19 ????????IPrincipal user = httpContext.User; 20 ????????if (!user.Identity.IsAuthenticated) 21 ????????{ 22 ????????????return false; 23 ????????} 24 ????????if ((this._usersSplit.Length != 0) && !this._usersSplit.Contains<string>(user.Identity.Name, StringComparer.OrdinalIgnoreCase)) 25 ????????{ 26 ????????????return false; 27 ????????} 28 ????????if ((this._rolesSplit.Length != 0) && !this._rolesSplit.Any<string>(new Func<string, bool>(user.IsInRole))) 29 ????????{ 30 ????????????return false; 31 ????????} 32 ????????return true; 33 ????} 34 ?35 ????private void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus) 36 ????{ 37 ????????validationStatus = this.OnCacheAuthorization(new HttpContextWrapper(context)); 38 ????} 39 ?40 ????protected virtual void HandleUnauthorizedRequest(AuthorizationContext filterContext) 41 ????{ 42 ????????filterContext.Result = new HttpUnauthorizedResult(); 43 ????} 44 ?45 ????public virtual void OnAuthorization(AuthorizationContext filterContext) 46 ????{ 47 ????????if (filterContext == null) 48 ????????{ 49 ????????????throw new ArgumentNullException("filterContext"); 50 ????????} 51 ????????if (OutputCacheAttribute.IsChildActionCacheActive(filterContext)) 52 ????????{ 53 ????????????throw new InvalidOperationException(MvcResources.AuthorizeAttribute_CannotUseWithinChildActionCache); 54 ????????} 55 ????????if (!filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true) && !filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true)) 56 ????????{ 57 ????????????if (this.AuthorizeCore(filterContext.HttpContext)) 58 ????????????{ 59 ????????????????HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache; 60 ????????????????cache.SetProxyMaxAge(new TimeSpan(0L)); 61 ????????????????cache.AddValidationCallback(new HttpCacheValidateHandler(this.CacheValidateHandler), null); 62 ????????????} 63 ????????????else 64 ????????????{ 65 ????????????????this.HandleUnauthorizedRequest(filterContext); 66 ????????????} 67 ????????} 68 ????} 69 ?70 ????protected virtual HttpValidationStatus OnCacheAuthorization(HttpContextBase httpContext) 71 ????{ 72 ????????if (httpContext == null) 73 ????????{ 74 ????????????throw new ArgumentNullException("httpContext"); 75 ????????} 76 ????????if (!this.AuthorizeCore(httpContext)) 77 ????????{ 78 ????????????return HttpValidationStatus.IgnoreThisRequest; 79 ????????} 80 ????????return HttpValidationStatus.Valid; 81 ????} 82 ?83 ????internal static string[] SplitString(string original) 84 ????{ 85 ????????if (string.IsNullOrEmpty(original)) 86 ????????{ 87 ????????????return new string[0]; 88 ????????} 89 ????????return original.Split(_splitParameter).Select((<>c.<>9__19_0 ?? (<>c.<>9__19_0 = new Func<string, <>f__AnonymousType1<string, string>>(<>c.<>9.<SplitString>b__19_0)))).Where((<>c.<>9__19_1 ?? (<>c.<>9__19_1 = new Func<<>f__AnonymousType1<string, string>, bool>(<>c.<>9.<SplitString>b__19_1)))).Select((<>c.<>9__19_2 ?? (<>c.<>9__19_2 = new Func<<>f__AnonymousType1<string, string>, string>(<>c.<>9.<SplitString>b__19_2)))).ToArray<string>(); 90 ????} 91 ?92 ????// Properties 93 ????public string Roles 94 ????{ 95 ????????get 96 ????????{ 97 ????????????return (this._roles ?? string.Empty); 98 ????????} 99 ????????set100 ????????{101 ????????????this._roles = value;102 ????????????this._rolesSplit = SplitString(value);103 ????????}104 ????}105 106 ????public override object TypeId107 ????{108 ????????get109 ????????{110 ????????????return this._typeId;111 ????????}112 ????}113 114 ????public string Users115 ????{116 ????????get117 ????????{118 ????????????return (this._users ?? string.Empty);119 ????????}120 ????????set121 ????????{122 ????????????this._users = value;123 ????????????this._usersSplit = SplitString(value);124 ????????}125 ????}126 127 ????// Nested Types128 ????[Serializable, CompilerGenerated]129 ????private sealed class <>c130 ????{131 ????????// Fields132 ????????public static readonly AuthorizeAttribute.<>c <>9 = new AuthorizeAttribute.<>c();133 ????????public static Func<string, <>f__AnonymousType1<string, string>> <>9__19_0;134 ????????public static Func<<>f__AnonymousType1<string, string>, bool> <>9__19_1;135 ????????public static Func<<>f__AnonymousType1<string, string>, string> <>9__19_2;136 137 ????????// Methods138 ????????internal <>f__AnonymousType1<string, string> <SplitString>b__19_0(string piece)139 ????????{140 ????????????return new { piece = piece, trimmed = piece.Trim() };141 ????????}142 143 ????????internal bool <SplitString>b__19_1(<>f__AnonymousType1<string, string> <>h__TransparentIdentifier0)144 ????????{145 ????????????return !string.IsNullOrEmpty(<>h__TransparentIdentifier0.trimmed);146 ????????}147 148 ????????internal string <SplitString>b__19_2(<>f__AnonymousType1<string, string> <>h__TransparentIdentifier0)149 ????????{150 ????????????return <>h__TransparentIdentifier0.trimmed;151 ????????}152 ????}153 }154 155 ?156 Collapse Methods157 ?
通过反汇编,得出如下结论:
1.提供四个虚方法OnAuthorization(AuthorizationContext filterContext),AuthorizeCore(HttpContextBase httpContext),HandleUnauthorizedRequest(AuthorizationContext filterContext)和OnCacheAuthorization(HttpContextBase httpContext)。
四个方法作用和关系是怎样的呢
OnAuthorization表示请求过程时身份验证,AuthorizeCore表示支持用户自定义身份验证,HandleUnauthorizeRequest表示当AuthorizeCore方法验证失败时,执行的操作,OnCacheAuthorization表示模块缓存权限。
(一) ASP.NET MVC 基架提供的验证
只需在需要验证的资源生加上[Authorize]特性即可。
1 ??[Authorize]2 ??public ActionResult Index()3 ??{4 ?????return View(); ;5 ??}
(二) 实现自定义验证机制
当未给Index() action添加验证限制时,匿名用户名能直接访问 /Default/Index
当给Index() action添加验证限制时,匿名用户名不能直接访问 /Default/Index,而被强制重定型到登陆页面,要求用户登陆。
(三) ASP.NET MVC验证级别
ASP.NET MVC提供了四种基本验证模式:匿名,全局,控制器和Action
1.匿名
1 public class DefaultController : Controller2 ????{3 ????????[AllowAnonymous]4 ????????public ActionResult Index()5 ????????{6 ????????????return View();7 ????????}8 ????}
2.action
1 public class DefaultController : Controller2 ????{3 ????????[CustomAuthorize]4 ????????public ActionResult Index()5 ????????{6 ????????????return View();7 ????????}8 ????}
3.Controller
1 [CustomAuthorize]2 ????public class DefaultController : Controller3 ????{4 ????????public ActionResult Index()5 ????????{6 ????????????return View();7 ????????}8 ????}
4.全局
1 public class FilterConfig2 ????{3 ????????public static void RegisterGlobalFilters(GlobalFilterCollection filters)4 ????????{5 ????????????filters.Add(new CustomAuthorizeAttribute());//给自定义验证注册6 ????????????filters.Add(new HandleErrorAttribute());7 ????????}8 ????}
扩展,当添加多个验证时,程序时如何执行的?通古Order值顺序执行
1 [Filter1(Order = 3)]2 [Filter2(Order = 2)]3 [Filter3(Order = 1)]4 public ActionResult Index()5 {6 ????return View(); ;7 }
三 总结
本篇文章主要从ASP.NET MVC框架设计角度,运用PD工具,通过UML分析ASP.NET MVC是如何实现资源过滤,如何实现权限控制等功能的,更细粒度的技术文章,在后续博文中更新。
【ASP.NET MVC系列】浅谈ASP.NET MVC资源过滤和授权
原文地址:https://www.cnblogs.com/wangjiming/p/8293978.html