在webform中,验证的流程大致如下图:
在AOP中:
在Filter中:
AuthorizeAttribute权限验证
登录后有权限控制,有的页面是需要用户登录才能访问的,需要在访问页面增加一个验证,也不能每个action都一遍。
1、写一个CustomAuthorAttribute,继承自AuthorizeAttribute,重写OnAuthorization方法,在里面把逻辑写成自己的。
2、有方法注册和控制器注册。
3、有全局注册,全部控制器全部action都生效。
但是在这个里面,首先要验证登录首页,首页没有邓丽,就跑到登录页面了,但是登录页面也要走特性里面的逻辑,又重定向到邓丽。。。循环了。。。。
这里有一个AlloAnonymous,这个标签就可以解决这个循环的问题,匿名支持,不需要登录就可以,但是单单加特性是没有用的,其实需要验证时支持,甚至可以说自己自定义一个特性也是可以的,这个特性里面是空的,只是为了用来做标记。
特性的使用范围,希望特性通用,在不同的系统,不同的地址登录,==》在特性上面加个传参的构造函数。
public class CustomAllowAnonymousAttribute : Attribute { }
CustomAuthorAttribute类
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class CustomAuthorizeAttribute : AuthorizeAttribute { private Logger logger = new Logger(typeof(CustomAuthorizeAttribute)); private string _LoginUrl = null; public CustomAuthorizeAttribute(string loginUrl = "~/Home/Login") { this._LoginUrl = loginUrl; } //public CustomAuthorizeAttribute(ICompanyUserService service) //{ //} //不行 public override void OnAuthorization(AuthorizationContext filterContext) { var httpContext = filterContext.HttpContext;//能拿到httpcontext 就可以为所欲为 if (filterContext.ActionDescriptor.IsDefined(typeof(CustomAllowAnonymousAttribute), true)) { return; } else if (filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(CustomAllowAnonymousAttribute), true)) { return; } else if (httpContext.Session["CurrentUser"] == null || !(httpContext.Session["CurrentUser"] is CurrentUser))//为空了, { //这里有用户,有地址 其实可以检查权限 if (httpContext.Request.IsAjaxRequest()) //httpContext.Request.Headers["xxx"].Equals("XMLHttpRequst") { filterContext.Result = new NewtonJsonResult( new AjaxResult() { Result = DoResult.OverTime, DebugMessage = "登陆过期", RetValue = "" }); } else { httpContext.Session["CurrentUrl"] = httpContext.Request.Url.AbsoluteUri; filterContext.Result = new RedirectResult(this._LoginUrl); //短路器:指定了Result,那么请求就截止了,不会执行action } } else { CurrentUser user = (CurrentUser)httpContext.Session["CurrentUser"]; //this.logger.Info($"{user.Name}登陆了系统"); return;//继续 } //base.OnAuthorization(filterContext); } }
Filter生效机制
为什么加个标签,继承AuthorizeAttribute,重写OnAuthorization方法就可以了呢?控制器已经实例化,调用ExecuteCore方法,找到方法名字,ControllerActionInvokee.InvokeAction,找到全部的Filter特性,InvokeAuthorize--result不为空,直接InvokeActionResult,为空就正常执行Action。
有一个实例类型,有一个方法名称,希望你反射执行
在找到方法后,执行方法前,可以检测下特性,来自全局的、来自控制器的、来自方法的。价差特性,特性是自己预定义的,按类执行,定个标识,为空就正常,不为空就跳转,正常就继续执行。
Filter原理和AOP面向切面编程
Filter是AOP思想的一种实现,其实就是ControllerActionInvoke这个类中,有个InvokeAction方法,控制器实例化之后,ActionInvoke前后,通过检测预定义Filter并且执行它,达到AOP的目的。
下面是InvokeAction的源码:
public virtual bool InvokeAction(ControllerContext controllerContext, string actionName) { if (controllerContext == null) { throw new ArgumentNullException("controllerContext"); } if (string.IsNullOrEmpty(actionName) && !controllerContext.RouteData.HasDirectRouteMatch()) { thr