asp.net core 拦击器制作的权限管理系统DEMO

Posted anang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 = 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 以上就是全部代码

以上代码有两个问题
1、无法在本次请求中选择要执行的控制器方法
虽然在 ActionExecutingContext.Controller有控制器实例并且可以直接调用,
控制器本身也是一个类
但是我就是感觉不是这样弄得。

2、保存用户信息的方法
其中可访问链接我是用list保存,也不知道有没有更好的方法。

Over





 






























以上是关于asp.net core 拦击器制作的权限管理系统DEMO的主要内容,如果未能解决你的问题,请参考以下文章

Asp.Net Core 2.0 项目实战NCMVC一个基于Net Core2.0搭建的角色权限管理开发框架

ASP .NET Core 身份登录管理器

ASP.NET Core 标识:角色管理器没有服务

Asp.net core IdentityServer4与传统基于角色的权限系统的集成

net core体系-web应用程序-4asp.net core2.0 项目实战-13基于OnActionExecuting全局过滤器,页面操作权限过滤控制到按钮级

具有用户权限的基于 JWT 令牌的授权 Asp.net core 2.0