最近在网上学习了一节有关于mvc对权限扩展定制的内容,感觉挺有意思的,今天特地实现了一下。写一篇这个过程的总结
AOP
在内容开始之前,不得不提一下AOP这个概念,在不破坏封装的前提下动态添加方法的功能。MVC中的特性就是基于这个思想,通常我们在一个控制器上添加一个特性,当调用这个控制器时,它先去执行这个特性中的内容,以达到对方法的扩展。
一.开始我们的正题
在mvc中我们通常去使用一个[Authorize]的注解去完成相应的功能,那我们有没有想过它是怎么实现的呢。通过反编译这个特性,这里面有一个重要的方法-OnAuthorization 用于处理我们的请求完成相应的授权操作,接下来我们通过重写这个方法,完成我们自己的定制
二.先写一下我们登录时的处理逻辑
if (u.PassWord==user.PassWord) { User currentUser = new Models.User { Name = u.Name, TelPhone = u.TelPhone, E_Mail = u.E_Mail }; //设置cookie HttpCookie myCookie = new HttpCookie("CurrentUser"); myCookie.Value = JsonConvert.SerializeObject(currentUser); myCookie.Expires = DateTime.Now.AddMinutes(5); HttpContext.Response.Cookies.Add(myCookie); //输出cookie //设置session base.HttpContext.Session["CurrentUser"] = u.Id.ToString(); base.HttpContext.Session.Timeout = 3; if (base.HttpContext.Session["CurrentUrl"]!=null) //判断当前请求的url进行页面跳转 { string url = base.HttpContext.Session["CurrentUrl"].ToString(); base.HttpContext.Session.Remove("CurrentUrl"); return Json(new UIResult(true,"登录成功",url)); //base.Redirect(url); } else { return Json(new UIResult(true, "登陆成功")); }
}
三.创建一个MyAuthorizeAttribute
public class MyAuthorizeAttribute: AuthorizeAttribute {
private string _loginUrl = ""; public MyAuthorizeAttribute() { _loginUrl = "/Login/Login"; } public MyAuthorizeAttribute(string url) { _loginUrl = url; } /// <summary> /// 重写父类的方法,执行动作前进行验证 /// </summary> /// <param name="filterContext"></param> public override void OnAuthorization(AuthorizationContext filterContext) { //base.OnAuthorization(filterContext); //filterContext.HttpContext 获取http请求的上下文,能获取HTTP 请求的所有 HTTP 特定的信息。
//通过判断Action或Controller上有没有定义MyAllowAnoymouseAttribute这个特性来进行放行,这个特性没有特别的作用只是在这里用于判断
if (filterContext.ActionDescriptor.IsDefined(typeof(MyAllowAnonymousAttribute), true) || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(MyAllowAnonymousAttribute),true)) { return; }
var httpContext = filterContext.HttpContext; if (httpContext.Session["CurrentUser"] ==null) { if (httpContext.Request.IsAjaxRequest()) //判断是否为Ajax请求 { filterContext.Result = new JsonResult() { Data = new UIResult(false, "登录过期") { } }; } else { httpContext.Session["CurrentUrl"] = httpContext.Request.Url.AbsoluteUri; filterContext.Result = new RedirectResult(_loginUrl); } //短路器:指定了Result,那么请求就截止了,不会再执行action } else { return; } } }
四.匿名登录 MyAllowAnonymousAttribute的实现
public class MyAllowAnonymousAttribute:Attribute { //没有什么特殊的方法实现,只是一个标记。用于判断 public MyAllowAnonymousAttribute() { } }
五.注册我们扩展的特性
1.在Action上注册
2.在Controller上注册
3.全局注册