今天把用户的菜单显示和页面的按钮显示都做好了,下面先来个效果图
接下来说下我实现的方法:
首先我在每个方法前面都加了这个属性,
/// <summary>
/// 表示当前Action请求为一个具体的功能页面
/// </summary>
public class AdminActionMethod : Attribute {
/// <summary>
/// 页面请求路径
/// </summary>
public string ActionUrl { get; set; }
/// <summary>
/// 页面操作代码
/// </summary>
public string RoleCode { get; set; }
/// <summary>
/// 页面返回类型(0:返回页面,1返回json格式)
/// </summary>
public int ActionResultType { get; set; }
}
当不需要验证的时候只要设置RoleCode="NoNeedAuthory"就行。
然后每次在执行方法之间都会进入到
public class AdminAuthory : ActionFilterAttribute {
public override void OnActionExecuting(ActionExecutingContext filterContext) {
//用MVC系统自带的功能 获取当前方法上的特性名称
bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(typeof(NoNeedAdminAuthory), inherit: true)
|| filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(NoNeedAdminAuthory), inherit: true);
if (skipAuthorization) {
return;
}
//检查是否登录
if (!WebCookieHelper.AdminCheckLogin()) {
filterContext.Result = new RedirectResult("~/Admin/Account/Login", true);
return;
}
//如果是超级管理就免去验证
if (WebCookieHelper.GetAdminId() == ) {
return;
}
//页面权限验证开始
var customAttributes = filterContext.ActionDescriptor.GetCustomAttributes(true);
if (customAttributes != null && customAttributes.Length > ) {
for (int i = ; i < customAttributes.Count(); i++) {
if (customAttributes.GetValue(i).GetType().Name == "AdminActionMethod") {//判断anction特性名称
string actionCode = (customAttributes[i] as AdminActionMethod).RoleCode;//获取特性功能按钮代码
string actionUrl = (customAttributes[i] as AdminActionMethod).ActionUrl;//获取特性功能地址
int actionResultType = (customAttributes[i] as AdminActionMethod).ActionResultType;//获取返回视图类型
if (actionCode == "NoNeedAuthory") {//不需要权限认证
return;
}
else { //判断权限是否符合
List<AuthorDesign.Model.AdminPageAction> pageActionList = AdminMenuHelper.GetNowAdminMenu();
var pageSelect = pageActionList.Where(m => m.PageUrl == actionUrl);
if (pageSelect != null && pageSelect.Count() > ) { //判断有无执行该页面的权利
//判断有误执行该动作权利
var codeList = AdminMenuHelper.LoadActionCodeList();
//先根据动作按钮代码查找到代码所在按钮Id
var codeSelect = codeList.Where(m => m.ActionCode == actionCode);
if (codeSelect != null && codeSelect.Count() > ) {
int codeId = codeSelect.First().Id;
JavaScriptSerializer serializer = new JavaScriptSerializer();
//判断codeId在角色动作列表中是否为选择状态
string roleActionList = pageSelect.First().RoleActionList; List<AuthorDesign.Web.Areas.Admin.Models.RolePageActionModel> roleActionListModel = serializer.Deserialize<List<AuthorDesign.Web.Areas.Admin.Models.RolePageActionModel>>(roleActionList);
if (roleActionListModel != null && roleActionListModel.Where(m => m.ActionId == codeId && m.actionChecked == ).Count() > ) {
//判断CodeId在管理员动作列表中是否为选择状态
List<AuthorDesign.Web.Areas.Admin.Models.RolePageActionModel> adminActionListModel = serializer.Deserialize<List<AuthorDesign.Web.Areas.Admin.Models.RolePageActionModel>>(pageSelect.First().AdminActionList);
if (adminActionListModel != null && adminActionListModel.Where(m => m.ActionId == codeId && m.actionChecked == ).Count() > ) {
StringBuilder sb = new StringBuilder();
sb.Append("[");
//传递在该页面可执行的按钮
foreach (var item in roleActionListModel) {
if (item.actionChecked == ) {
var needChangeAction = adminActionListModel.Where(m => m.ActionId == item.ActionId).FirstOrDefault();
if (needChangeAction == null) {
item.actionChecked = ;
}
else if (needChangeAction.actionChecked == ) {
item.actionChecked = ;
}
}
AuthorDesign.Model.PageAction OneAction = codeList.Where(m => m.Id == item.ActionId).FirstOrDefault();
sb.Append("{").Append("\"").Append("ActionName").Append("\"").Append(":").Append("\"").Append(OneAction == null ? "" : OneAction.ActionCode).Append("\"").Append(",").Append("\"").Append("IsChecked").Append("\"").Append(":").Append(item.actionChecked).Append("}").Append(","); }
sb.Remove(sb.Length - , );
sb.Append("]");
filterContext.Controller.ViewBag.CanOperationActionList = sb.ToString();
}
else {
if (actionResultType == ) {
filterContext.Result = new RedirectResult("~/Admin/Home/NoAuthory", true);
}
else if (actionResultType == ) {
filterContext.Result = new JsonResult() { Data = new { state = "error", message = "您暂无权限操作" } };
}
return;
}
}
else {
if (actionResultType == ) {
filterContext.Result = new RedirectResult("~/Admin/Home/NoAuthory", true);
}
else if (actionResultType == ) {
filterContext.Result = new JsonResult() { Data = new { state = "error", message = "您暂无权限操作" } };
}
return;
} }
else {
if (actionResultType == ) {
filterContext.Result = new RedirectResult("~/Admin/Home/NoAuthory", true);
}
else if (actionResultType == ) {
filterContext.Result = new JsonResult() { Data = new { state = "error", message = "您暂无权限操作" } };
}
return;
}
}
else {
if (actionResultType == ) {
filterContext.Result = new RedirectResult("~/Admin/Home/NoAuthory", true);
}
else if (actionResultType == ) {
filterContext.Result = new JsonResult() { Data = new { state = "error", message = "您暂无权限操作" } };
}
return;
}
}
}
}
} base.OnActionExecuting(filterContext);
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class NoNeedAdminAuthory : Attribute {
}
这是MVC的机制,这个方法是重写了执行方法之前的这个方法,不过需要在控制器上或者方法上加上下面这个代码
那么接下来就说下我的判断思路:
//检查是否登录
if (!WebCookieHelper.AdminCheckLogin()) {
filterContext.Result = new RedirectResult("~/Admin/Account/Login", true);
return;
}
这是用来先检测下用户是否登录,如果没有登录则直接回到登录页面,
//如果是超级管理就免去验证
if (WebCookieHelper.GetAdminId() == ) {
return;
}
这是如果进来的用户是超级管理员那么就直接显示要显示的页面页面即可,左边菜单栏晚点讲。
//页面权限验证开始
var customAttributes = filterContext.ActionDescriptor.GetCustomAttributes(true);
if (customAttributes != null && customAttributes.Length > ) {
for (int i = ; i < customAttributes.Count(); i++) {
if (customAttributes.GetValue(i).GetType().Name == "AdminActionMethod") {//判断anction特性名称
string actionCode = (customAttributes[i] as AdminActionMethod).RoleCode;//获取特性功能按钮代码
string actionUrl = (customAttributes[i] as AdminActionMethod).ActionUrl;//获取特性功能地址
int actionResultType = (customAttributes[i] as AdminActionMethod).ActionResultType;//获取返回视图类型
利用这个来抓取用户当前要执行的方法,然后对其作出相应的处理,
List<AuthorDesign.Model.AdminPageAction> pageActionList = AdminMenuHelper.GetNowAdminMenu();
这行代码用来加载当前要显示的全部页面
/// <summary>
/// 获取管理员可操作菜单列表
/// </summary>
/// <param name="adminId">管理员Id</param>
/// <returns></returns>
public static List<Model.AdminPageAction> GetAdminMenu(int adminId) {
if (CacheHelper.IsExistCache("AdminMenuList")) {
Dictionary<int, List<Model.AdminPageAction>> adminMenuListDic = CacheHelper.GetCache("AdminMenuList") as Dictionary<int, List<Model.AdminPageAction>>;
List<Model.AdminPageAction> adminMenuList = adminMenuListDic[adminId];
if (adminMenuList == null) {
adminMenuList = EnterRepository.GetRepositoryEnter().GetPageMenuRepository.GetAdminShowPage(adminId);
adminMenuListDic.Add(adminId, adminMenuList);
CacheHelper.AddCache("AdminMenuList", adminMenuListDic, );
}
return adminMenuList;
}
else {
List<Model.AdminPageAction> adminMenuList = EnterRepository.GetRepositoryEnter().GetPageMenuRepository.GetAdminShowPage(adminId);
Dictionary<int, List<Model.AdminPageAction>> adminMenuListDic = new Dictionary<int, List<Model.AdminPageAction>>();
adminMenuListDic.Add(adminId, adminMenuList);
CacheHelper.AddCache("AdminMenuList", adminMenuListDic, );
return adminMenuList;
}
//if (CacheHelper.IsExistCache("AdminMenuList_"+adminId)) {
// return CacheHelper.GetCache("AdminMenuList_" + adminId) as List<Model.AdminPageAction>;
//}
//else {
// List<Model.AdminPageAction> adminMenuList = EnterRepository.GetRepositoryEnter().GetPageMenuRepository.GetAdminShowPage(adminId);
// CacheHelper.AddCache("AdminMenuList_" + adminId, adminMenuList, 1);
// return adminMenuList;
//}
//return EnterRepository.GetRepositoryEnter().GetPageMenuRepository.GetAdminShowPage(adminId);
}
/// <summary>
/// 获取当前管理员可操作菜单列表(超级管理员另取)
/// </summary>
/// <returns></returns>
public static List<Model.AdminPageAction> GetNowAdminMenu() {
return GetAdminMenu(WebCookieHelper.GetAdminId());
}
这里我用缓存做了下处理,不知道处理的好不好,还望你们指点我一下。
var pageSelect = pageActionList.Where(m => m.PageUrl == actionUrl);
if (pageSelect != null && pageSelect.Count() > ) { //判断有无执行该页面的权利
这个是用来判断当前执行的方法是否在全部要显示的页面之中,如果不是则直接输出,是的话继续往下走。
//判断有误执行该动作权利
var codeList = AdminMenuHelper.LoadActionCodeList();
//先根据动作按钮代码查找到代码所在按钮Id
var codeSelect = codeList.Where(m => m.ActionCode == actionCode);
if (codeSelect != null && codeSelect.Count() > ) {
int codeId = codeSelect.First().Id;
JavaScriptSerializer serializer = new JavaScriptSerializer();
//判断codeId在角色动作列表中是否为选择状态
string roleActionList = pageSelect.First().RoleActionList;
这里是先判断了当前执行的方法按钮是否在该管理员所属的角色 可操作的按钮之中,不是的话直接输出,如果是的话则继续往下走。
List<AuthorDesign.Web.Areas.Admin.Models.RolePageActionModel> roleActionListModel = serializer.Deserialize<List<AuthorDesign.Web.Areas.Admin.Models.RolePageActionModel>>(roleActionList);
if (roleActionListModel != null && roleActionListModel.Where(m => m.ActionId == codeId && m.actionChecked == ).Count() > ) {
//判断CodeId在管理员动作列表中是否为选择状态
List<AuthorDesign.Web.Areas.Admin.Models.RolePageActionModel> adminActionListModel = serializer.Deserialize<List<AuthorDesign.Web.Areas.Admin.Models.RolePageActionModel>>(pageSelect.First().AdminActionList);
if (adminActionListModel != null && adminActionListModel.Where(m => m.ActionId == codeId && m.actionChecked == ).Count() > ) {
StringBuilder sb = new StringBuilder();
sb.Append("[");
//传递在该页面可执行的按钮
foreach (var item in roleActionListModel) {
if (item.actionChecked == ) {
var needChangeAction = adminActionListModel.Where(m => m.ActionId == item.ActionId).FirstOrDefault();
if (needChangeAction == null) {
item.actionChecked = ;
}
else if (needChangeAction.actionChecked == ) {
item.actionChecked = ;
}
}
AuthorDesign.Model.PageAction OneAction = codeList.Where(m => m.Id == item.ActionId).FirstOrDefault();
sb.Append("{").Append("\"").Append("ActionName").Append("\"").Append(":").Append("\"").Append(OneAction == null ? "" : OneAction.ActionCode).Append("\"").Append(",").Append("\"").Append("IsChecked").Append("\"").Append(":").Append(item.actionChecked).Append("}").Append(","); }
sb.Remove(sb.Length - , );
sb.Append("]");
filterContext.Controller.ViewBag.CanOperationActionList = sb.ToString();
这部分就是主要用来判断当前执行的方法是否在该管理员可执行的按钮之中,如果在的话那么将改页面的按钮以及是否可操作状态通过ViewBag进行传到前台,然后前台利用Js来移除相对应的不显示按钮。
左边的菜单按钮部分待会上源码自己去看下吧
那么简单的用户角色权限管理在这里就可以结束了。但是我发现有个问题,我也不知道是为什么:看下面
就是我用火狐的时候,发现点击某些链接的时候会不经过那个action的方法,直接跳到登录页面,这是为什么,我碰到好几次了,求帮忙解决下。
github地址:https://github.com/yjqGitHub/AuthoryDesign
有什么地方写的不好的还希望大家都指出来啊