一、首先过滤菜单权限
一. 此处是基于ligerUl框架的前端展示实现的菜单权限过滤,实现的步骤都大同小异,重点是本篇实现的思想。
1. 注释掉原本固定的菜单展示
2. 向后端发送一个getJSON异步请求
//发送异步请求,请求的控制器和请求的方法,请求的参数,返回的参数,并且将返回的参数赋值给links $.getJSON("/Home/Getmenus", {}, function (data) { links = data; linksInit(); onResize(); })
3. 写Getmenus方法对应的内容
该方法中具体需要实现如下:
a. 首先按照用户-角色-权限查找菜单权限,放在一个集合中
b. 按照用户-权限查找菜单权限,放在一个集合中
c. 将两个集合合并成一个集合
d . 将禁止的集合从中清除出去
e. 将重复的清除出去
g. 把过滤好的集合返回到前端
IBLL.IUserInfoService UserInfoService { get; set; } //首先构建出该类的实例
#region 过滤登录用户的菜单权限 /// <summary> /// 1: 可以按照用户---角色---权限这条线找出登录用户的权限,放在一个集合中。 /// 2:可以按照用户---权限这条线找出用户的权限,放在一个集合中。 /// 3:将这两个集合合并成一个集合。 /// 4:把禁止的权限从总的集合中清除。 /// 5:将总的集合中的重复权限清除。 /// 6:把过滤好的菜单权限生成JSON返回。 /// </summary> /// <returns></returns> public ActionResult Getmenus() { //1: 可以按照用户---角色---权限这条线找出登录用户的权限,放在一个集合中。 //获取登录用户的信息 var userInfo = UserInfoService.LoadEntities(u => u.ID == Loginuser.ID).FirstOrDefault(); //获取登录用户的角色. var userRoleInfo = userInfo.RoleInfo; //根据登录用户的角色获取对应的菜单权限。 short actionTypeEnum = (short)ActionTypeEnum.MenumActionType; var loginUserMenuActions = (from r in userRoleInfo from a in r.ActionInfo where a.ActionTypeEnum == actionTypeEnum select a).ToList(); //下面语句是错误的,allUserActions是一个大集合该集合中包含了很多小的集合,所以变量b为集合类型 //var allUserActions = from r in userRoleInfo // select r.ActionInfo; //var mm = from b in allUserActions // where b.ActionTypeEnum == actionTypeEnum // select b; // 2:可以按照用户---权限这条线找出用户的权限,放在一个集合中。 var userActions = from a in userInfo.R_UserInfo_ActionInfo select a.ActionInfo; var userMenuActions = (from a in userActions where a.ActionTypeEnum == actionTypeEnum select a).ToList(); // a.ActionInfo不是一个集合,注意理解权限表与用户权限关系表之间的对应关系 //var userMenuActionse = from a in userInfo.R_UserInfo_ActionInfo // from b in a.ActionInfo // where b.ActionTypeEnum == actionTypeEnum // select b; //3:将这两个集合合并成一个集合。 loginUserMenuActions.AddRange(userMenuActions); //4:把禁止的权限从总的集合中清除。 //查询出禁止的 var forbidActions = (from a in userInfo.R_UserInfo_ActionInfo where a.IsPass == 0 select a.ActionInfoID).ToList(); //过滤查询出不包含禁止的,此处需要些一个方法 var loginUserAllowActions = loginUserMenuActions.Where(a => !forbidActions.Contains(a.ID)); //5:将总的集合中的重复权限清除。,此处需要单独写一个方法,方法的内容如下。 var lastLoginUserActions = loginUserAllowActions.Distinct(new EqualityComparer()); //6:把过滤好的菜单权限生成JSON返回。 var temp = from a in lastLoginUserActions select new { icon = a.MenuIcon, title = a.ActionInfoName, url = a.Url }; return Json(temp, JsonRequestBehavior.AllowGet); //此处返回一个temp,与指明只提交get的请求。 } #endregion
上方去重的时候,需要单独写一个该方法
namespace Model { public class EqualityComparer:IEqualityComparer<ActionInfo> { public bool Equals(ActionInfo x, ActionInfo y) { return x.ID == y.ID; } public int GetHashCode(ActionInfo obj) { return obj.GetHashCode(); } } }
这样就过滤成功了,但是这样还没有完,因为如果用户知道某一个菜单中的子菜单,直接输入子菜单对应的地址,还是会进入菜单中,所以这样还是不安全,那么就需要再做下方的步骤。
就是在baseCollections中实现非菜单权限的过滤,实现的步骤就是根据登录用户,与请求的方式与请求的地址,并且根据用户,角色,权限,与用户,权限两条线去查询条件查询是否满足。并且baseCollections是所有控制器的基类,每次执行之前都会执行该类。
using IBLL; using Model; using Spring.Context; using Spring.Context.Support; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace OA_MVC.Controllers { public class BaseController : Controller { public UserInfo Loginuser { get; set; } /// <summary> /// 控制器每次执行之前会先执行该方法 /// </summary> /// <param name="filterContext"></param> protected override void OnActionExecuting(ActionExecutingContext filterContext) { base.OnActionExecuting(filterContext); bool isSucess = false; if (Request.Cookies["sessionId"] != null) { //首先获取到Memcache对应的cookies值。 string sessionId = Request.Cookies["sessionId"].Value; object obj = Common.MemcacheHelper.Get(sessionId); if (obj != null) { //UserInfo userinfo = obj as UserInfo; UserInfo userinfo = Common.SerializeHelper.DeserializeToObject<UserInfo>(obj.ToString()); Loginuser = userinfo; isSucess = true; Common.MemcacheHelper.Set(sessionId, obj, DateTime.Now.AddMinutes(20));//模拟滑动过期时间 //从此处开始,完成权限校验。 //获取用户请求的URL地址. //如果是Request.Url获取到的是http://localhost:40008/Home/home //但是Request.Url.AbsolutePath获取到的是/Home/home string url = Request.Url.AbsolutePath.ToLower(); //获取请求的方式. string httpMehotd = Request.HttpMethod; //根据获取的URL地址与请求的方式查询权限表。 IApplicationContext ctx = ContextRegistry.GetContext(); IBLL.IActionInfoService ActionInfoService = (IBLL.IActionInfoService)ctx.GetObject("ActionInfoService"); var actionInfo = ActionInfoService.LoadEntities(a => a.Url == url && a.HttpMethod == httpMehotd).FirstOrDefault(); //判断用户是否具有所访问的地址对应的权限 IUserInfoService UserInfoService = (IUserInfoService)ctx.GetObject("UserInfoService"); var loginUserInfo = UserInfoService.LoadEntities(u => u.ID == Loginuser.ID).FirstOrDefault(); //1:可以先按照用户权限这条线进行过滤。 var isExt = (from a in loginUserInfo.R_UserInfo_ActionInfo where a.ActionInfoID == actionInfo.ID select a).FirstOrDefault(); if (isExt != null) { if (isExt.IsPass == 1) { return; } else { filterContext.Result = Redirect("/Error.html"); return; } } //2:按照用户角色权限这条线进行过滤。 var loginUserRole = loginUserInfo.RoleInfo; var count = (from r in loginUserRole from a in r.ActionInfo where a.ID == actionInfo.ID select a).Count(); if (count < 1) { filterContext.Result = Redirect("/Error.html"); return; } //到此处结束 } } if (!isSucess) { filterContext.Result = Redirect("/Login/Index"); } } } }