最近找工作,没事东拼西凑了一个权限管理系统,仅供参考。
开发环境vs2019,sqlserver express2017
后台使用asp.net core,数据库使用ef core访问,前台使用jquery+bootstrap+admilte
先上个图
说明:
1、系统前台使用ajax访问后台,返回数据由自定义方法public IActionResult Json(Result result, ToastType toastType, string message)包装,在前端用ajaxToast方法处理返回的数据
2、site.js中包含了一些自定义的js函数对表单进行处理,表单验证使用jquery.validate
3、系统分为四个模块:用户管理、角色管理、菜单管理、权限管理。大部分都是简单的增、删、改、查,其中用户管理可以配置和角色的关系,角色管理可以配置和权限的关系。
4、权限和MVC的Action对应,每个权限的访问由PermissionAccess标记控制,标记分为匿名访问(不用登陆就可以访问)、默认访问(登陆后都可以访问)、特定访问(需要配置角色、权限、用户之间的关系才能访问)、跟随父权限访问(每个操作都可能会附带一些ajax访问,代码中直接配置)。
5、权限的显示由PermissionDisplay来控制,分别对应菜单、按钮、接口。菜单的生成在Home/Index中。每个页面对应按钮的显示、隐藏由BaseController中生成的 ViewBag.PCodes,在前台_Layout.cshtml中的refreshButtonPermission函数控制
6、代码主要逻辑在BaseController中,通过重写OnActionExecuting控制权限
public override void OnActionExecuting(ActionExecutingContext context) { base.OnActionExecuting(context); //获取缓存数据 var allPermission = CacheHelper.GetCache<List<Permission>>(CacheKeys.AllPermission); //1、如果当前有匿名标记,则不需要登陆直接可以访问 //2、判断登陆,如果没有登陆则跳转到登陆页面 //3、如果当前有默认标记,则直接访问 //4、判断当前用户是否有权限访问当前方法 //获取请求的路由对应权限 var area = context.RouteData.Values["area"]?.ToString(); var controller = context.RouteData.Values["controller"]?.ToString(); var actoin = context.RouteData.Values["action"]?.ToString(); var requestRoute = $"/{area}/{controller}/{actoin}".Replace("//", "/"); var requestPermission = allPermission.FirstOrDefault(t => t.Route == requestRoute); //获取自定义特性的父权限路由对应的访问权限 var filters = context.Filters.Where(t => (t as ParentPermissionAttribute) != null); var filterRoutes = filters.Select(t => { var attribute = t as ParentPermissionAttribute; return $"/{attribute.Area}/{attribute.Controller}/{attribute.Action}".Replace("//", "/"); }).ToList(); var actionPermissions = allPermission.Where(t => filterRoutes.Any(m => m == t.Route)).ToList(); if (requestPermission != null) { actionPermissions.Add(requestPermission); } if (actionPermissions.Count == 0) { context.Result = Content("该权限未开放"); return; } //包含匿名访问权限,直接访问 if (actionPermissions.Any(t => t.Access == PermissionAccess.Anonymous)) { return; } //判断是否登陆,后面的验证都是登陆为基础 if (CurrentUser == null) { context.Result = new RedirectResult($"/SystemManage/Account/Login?returnUrl={HttpUtility.UrlEncode(Request.Path)}"); return; } //如果该功能显示为页面,处理页面按钮显示 if (requestPermission != null && requestPermission.Display == PermissionDisplay.Menu) { //查看该页面下所有的按钮权限 var buttons = allPermission.Where(t => t.Display == PermissionDisplay.Button && t.MenuId == requestPermission.MenuId).ToList(); var dict = new Dictionary<string, bool> { //添加默认,防止为空时页面出错 { "", true } }; buttons.ForEach(t => { //生成按钮在当前用户下的权限列表 dict.Add(t.Code, CurrentPermissions.Any(m => m.Id == t.Id)); }); ViewBag.PCodes = JsonConvert.SerializeObject(dict); } //默认权限,登陆后访问 if (actionPermissions.Any(t => t.Access == PermissionAccess.Default)) { return; } //最后验证特定权限 //用户所有权限是否包含当前权限 var hasPermission = false; foreach (var item in CurrentPermissions) { if (actionPermissions.Any(t => t.Id == item.Id)) { hasPermission = true; break; } } if (hasPermission) { return; } else { context.Result = Content("无权限访问"); return; } }
7、大部分代码都有注释,直接断点调试就能查看就行了
8、数据库直接用HelloPermission.bak还原。也可以由ef生成数据库,初始化数据在script.sql中
9、代码地址 https://pan.baidu.com/s/1lFn5LqnCjLhtK9gVoAOiFA 提取码 tpc6
原文地址:https://www.cnblogs.com/donghaidong/p/11231114.html