asp.net core 拦击器制作的权限管理系统DEMO
效果图
没有登陆不会执行请求日期的方法,不管是否登陆都不允许访问请求时间方法
验证不通过是会进行转发到Home/error方法中,
代码附上:
[Route("[controller]/[action]")] public class HomeController : BaseController { /// <summary> /// Ajax请求页面 /// </summary> /// <param name="username"></param> /// <param name="password"></param> /// <returns></returns> [HttpGet] public IActionResult AjaxView() { return View(); } /// <summary> /// 登陆接口 /// </summary> /// <param name="username"></param> /// <param name="password"></param> /// <returns></returns> [HttpGet] public IActionResult Login() { LoginMember(); return Json("登陆成功"); } /// <summary> /// 清除登陆信息 /// </summary> /// <returns></returns> [HttpGet] public IActionResult ClearLogin() { ClearMember(); return Json("注销成功"); } /// <summary> /// 登陆后也不能请求的接口 /// </summary> /// <returns></returns> public IActionResult GetNoData() { return Json("时间是" + DateTime.Now.ToLongTimeString()); } /// <summary> /// 请求数据接口 /// </summary> /// <returns></returns> public IActionResult GetData() { return Json("今天是" + DateTime.Now.ToLongDateString()); } /// <summary> /// 请求页面接口 /// </summary> /// <returns></returns> public IActionResult GetDataView() { return View(); } /// <summary> /// 请求不通过接口 /// </summary> /// <returns></returns> public IActionResult Error() { return Json("你没有权限"); } }
AjaxView视图页:
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>AjaxView</title> <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script> <script type="text/javascript" > $(function () { $("#Login").click(function () { $.get("/Home/Login", "", function (data) { alert(data); }) }) $("#ClearLogin").click(function () { $.get("/Home/ClearLogin", "", function (data) { alert(data); }) }) $("#Getdata").click(function () { $.get("/Home/GetData", "", function (data) { alert(data); }) }) $("#GetTime").click(function () { $.get("/Home/GetNoData", "", function (data) { alert(data); }) }) }) </script> </head> <body> <button id="Login">登陆</button> <button id="ClearLogin">注销</button> <button id="Getdata">请求日期</button> <button id="GetTime">请求时间</button> </body> </html>
4个请求
支持类(用户类与权限类、枚举):
/// <summary> /// 用户类 /// </summary> public class Member { public string Name { get; set; } //允许请求的连接 public IEnumerable<RightsManagement> RightsList { get; set; } } /// <summary> /// 权限类 /// </summary> public class RightsManagement { public int ID { get; set; } /// <summary> /// 允许请求的路径 /// </summary> public string AllowRequest { get; set; } } public enum ErrorEnum { /// <summary> /// 没有登陆 /// </summary> NoLogin=1, /// <summary> /// 不允许访问 /// </summary> NoAllow=2, /// <summary> /// 可以访问 /// </summary> OK=3 }
全局变量
/// <summary> /// error 方法地址 /// </summary> protected string ErrorAction { get; private set; } = "Error"; /// <summary> /// error 方法地址 /// </summary> protected string ErrorController { get; private set; } = "Home"; /// <summary> /// 用户类 ,为了直观点就这样弄了 /// </summary> protected static Member member { get; private set; } /// <summary> /// 所有人都能访问的接口,以下接口不会被拦截 /// </summary> protected List<RightsManagement> RightsList { get; set; } = new List<RightsManagement>() { new RightsManagement(){ ID=3, AllowRequest="Home/Login" }, new RightsManagement(){ ID=4, AllowRequest="Home/ClearLogin" }, new RightsManagement(){ ID=5, AllowRequest="Home/Error" } , new RightsManagement(){ ID=5, AllowRequest="Home/AjaxView" } }; private ErrorEnum errorEnum;
登陆与注销函数
/// <summary> /// 登陆函数 /// </summary> public void LoginMember() { member = new Member() { Name = "张三", RightsList = new List<RightsManagement>() { new RightsManagement(){ ID=1, AllowRequest="Home/GetData"//接口 }, new RightsManagement(){ ID=2, AllowRequest="Home/GetDataView"//视图页 } } }; } /// <summary> /// 清除登陆信息 /// </summary> public void ClearMember() { member = null; }
拦截器重写了父类的
OnActionExecutionAsync方法
如果不是asp.net core 将不会有这个方法
OnActionExecuting方法似乎无法决定控制器执行的方法,
/// <summary> /// 请求开始前异步调用 /// </summary> /// <param name="context">参数</param> /// <param name="next">一个已经封装好的委托</param> /// <returns></returns> public override Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { thecontext = context; //获取请求的路径 并进行拼接 string theControllerAndAction = context.ActionDescriptor.RouteValues["controller"] + "/" + context.ActionDescriptor.RouteValues["action"]; if (RightsList.Where(d=>d.AllowRequest== theControllerAndAction).Count()>0) { //允许默认允许的请求通过 return base.OnActionExecutionAsync(context, next); } //定义一个委托 用于表示next下一步执行的方法 ActionExecutionDelegate thenext = new ActionExecutionDelegate(TaskOnActionExecutionAsync); if (member == null) { //没有登陆 errorEnum = ErrorEnum.NoLogin; } else { if (member.RightsList.Where(d => d.AllowRequest == theControllerAndAction).Count() == 0) { //没有请求的权利 errorEnum = ErrorEnum.NoAllow; } else { errorEnum = ErrorEnum.OK; //用base方法的去处理验证通过的请求, //因为我不知道转发请求的性能是否有额外开销 return base.OnActionExecutionAsync(context, next); } } return base.OnActionExecutionAsync(context, thenext); }
Task 方法
Task<ActionExecutedContext> TaskOnActionExecutionAsync() { Task<ActionExecutedContext> thetask = new Task<ActionExecutedContext>(funcOnActionExecutionAsync, thecontext); thetask.Start(); return thetask; }
//这是一个全局的临时变量,在控制器中 每次请求都会重置他
ActionExecutingContext thecontext;
funcOnActionExecutionAsync方法
ActionExecutedContext funcOnActionExecutionAsync(object o) { ActionExecutingContext theaction = o as ActionExecutingContext; ActionExecutedContext theactionExecutedContext = new ActionExecutedContext(theaction, theaction.Filters, theaction.Controller); //表示跳过控制器方法访问直接返回数据给浏览器,也就是不跳转不进入控制器方法但是有异常信息返回 //theaction.Result = Json("请求成功"); switch (errorEnum) { case ErrorEnum.NoLogin:
//theaction.Result =new RedirectResult("/Home/Error");进行重定向
theaction.Result = RedirectToAction(ErrorAction, ErrorController);
break; case ErrorEnum.NoAllow: theaction.Result = RedirectToAction(ErrorAction, ErrorController); break; case ErrorEnum.OK: theaction.Result = RedirectToAction(theaction.ActionDescriptor.RouteValues["action"], theaction.ActionDescriptor.RouteValues["controller"]); break; default: break; } return theactionExecutedContext; }
OK 以上就是全部代码
其中可访问链接我是用list保存,也不知道有没有更好的方法。
Over