前言
- 這一篇我們將完成系統的權限設置功能以及不同角色用戶登錄系統后動態加載菜單。注意:此示例權限只針對菜單級,如果園友需要更復雜的系統權限設置,可以拓展到按鈕級或屬性級。
- 用戶的登錄采用Form認證來實現,這樣可以有效地防止非授權用戶或頁面鏈接對系統造成不安全的操作。
權限設置模塊
- 頁面采用角色列表和菜單列表勾選的方式,即選擇角色后勾選可以操作的菜單,這樣具有才角色的用戶就具有操作這些菜單的權限。界面設置如下:

- 界面選擇的roleID和menuID我們采用字符串的方式進行拼接。在controller中采用object類型進行接收,然后進行轉化后就可以得到傳入的值。權限設置的參考代碼如下:
public bool SetPermit(object RoleID, object MenuIDs) { try { string[] roleArr = RoleID as string[]; long roleID = Convert.ToInt64(roleArr[0].ToString()); S_Role role = context.S_Roles.Where(x => x.ID.Equals(roleID)).FirstOrDefault(); //獲取角色 role.S_Menus = new List<S_Menu>(); //刪除先前設置的roleID的數據 List<S_Menu> listdate = context.S_Roles.Where(x => x.ID.Equals(roleID)).FirstOrDefault().S_Menus.ToList(); foreach (var item in listdate) { role.S_Menus.Remove(item); } //寫入現有的數據 string[] MenuArr = MenuIDs as string[]; string[] MenuArrString = MenuArr[0].ToString().TrimEnd(',').Split(',').ToArray(); List<long> arr = new List<long>(); foreach (var item in MenuArrString) { arr.Add(Convert.ToInt64(item)); } //必須轉化為list集合,否則會出現“已有打開的與此 Command 相關聯的 DataReader,必須首先將它關閉”錯誤 List<S_Menu> query = (from m in context.S_Menus where arr.Contains(m.ID) select m).ToList(); foreach (S_Menu menu in query) { role.S_Menus.Add(menu); menu.S_Roles = new List<S_Role>(); menu.S_Roles.Add(role); } //EF默認啟用了事務提交 context.SaveChanges(); return true; } catch { return false; } }
- 由於想要在權限設置成功后能夠反映角色擁有操作哪些菜單的權限,因此,我們需要對角色的easyui-datagrid追加點擊事件,並且異步加載具有的菜單權限。Easyui-Datagrid本身具有一個很有用的數據方法unselectAll(取消選中當前頁所有的行)。但需要放置在選中的菜單權限之前。參考代碼如下:
$('#dg').datagrid({ onClickRow: function (index, data) { var row = $('#dg').datagrid('getSelected'); if (row) { var RoleID = row.ID; $.ajax({ url: '/System/GetPermit', type: 'POST', data: { RoleID: RoleID }, success: function (data) { $('#dgMenu').treegrid('unselectAll'); //重新加載 $('#dgMenu').treegrid({ onLoadSuccess: function (dataaa) { $.each(data, function (index, item) { $('#dgMenu').treegrid('selectRow', item); //選中設置的權限 }); }}); } })}} });
系統登錄用戶獲取菜單操作權限
- 在我們把權限設置模塊完成后就可以使不同角色的用戶登錄系統后操作不同的菜單權限。由於菜單采用的是easyui-tree來綁定的數據,所以我們需要定義一個符合easyui-tree屬性的數據模型,這樣就可以序列化easyui-tree識別的json數據格式呢。(這和之前的easyui-treegrid使用方式是一樣的)。參考代碼如下:
public class mod_S_RoleMenuTree { public long id { get; set; } // 節點的ID public string text { get; set; } //節點顯示的文字 public string iconCls { get; set; } public string url { get; set; } public int treelevel { get; set; } //節點狀態,有兩個值 'open' or 'closed', 默認為'open'. 當為‘closed’時說明此節點下有子節點否則此節點為葉子節點 public string state { get; set; } public List<mod_S_RoleMenuTree> children { get; set; }// 子節點集合 }
- 在MainController中我們可以根據登錄的用戶名獲取該用戶角色所具有的菜單權限。由於此示例的菜單只設置了兩級,所以沒有做遞歸。如果需要多級菜單,可以參照上一篇文章將以下方法修改成遞歸方法,參考代碼如下:
public ActionResult GetRoleMenus() { string strUser = System.Web.HttpContext.Current.User.Identity.Name; List<S_Menu> listData = IS_Role.GetRoleMenus(strUser); var listDataParent = listData.Where(x => x.PID.Equals(null)).OrderBy(x => x.SerialNO); List<mod_S_RoleMenuTree> DataModel = new List<mod_S_RoleMenuTree>(); foreach (var item in listDataParent) { mod_S_RoleMenuTree model = new mod_S_RoleMenuTree(); model.id = item.ID; model.text = item.MenuName; model.iconCls = item.Icon; model.state = "open"; model.url = item.Link; model.treelevel = item.Level; model.children = new List<mod_S_RoleMenuTree>(); var children = listData.Where(x => x.PID.Equals(item.ID)).OrderBy(x => x.SerialNO); foreach (var childitem in children) { mod_S_RoleMenuTree childmodel = new mod_S_RoleMenuTree(); childmodel.id = childitem.ID; childmodel.text = childitem.MenuName; childmodel.iconCls = childitem.Icon; childmodel.state = "open"; childmodel.url = childitem.Link; model.treelevel = childitem.Level; model.children.Add(childmodel); } DataModel.Add(model); } return Json(DataModel, JsonRequestBehavior.AllowGet); }
- 再將MainController中的Index視圖中的獲取菜單數據的代碼替換成以下代碼,這樣我們可以動態從數據庫中讀取菜單,而不是直接讀取json文件。
<ul class="easyui-tree" id="txt" data-options="url:'/Main/GetRoleMenus',method:'get',animate:true,lines:true"></ul>
登錄功能
- 我們為系統設置了連個賬戶admin\Jack,admin具有管理員角色,Jack具有操作員角色,因此兩個用戶登錄后看到的菜單是不一樣的。用戶登錄參考代碼如下:
[HttpPost] public ActionResult Login(mod_Account model) { if (null != model){ if (IS_User.Login(model.UserName, DESEncrypt.Encrypt(model.UserPwd))){ System.Web.Security.FormsAuthentication.SetAuthCookie(model.UserName, false); return RedirectToAction("Index", "Main"); } else{ return View(); } } else{ return View(); } }
- 由於采用Form認證,所以我們還需要在配置文件中修改一下代碼:
<authentication mode="Forms"> <forms loginUrl="/Account/Login" timeout="2880" protection="All" /> </authentication> <authorization> <deny users="?"/> </authorization>
- 退出時,需要注銷認證用戶,參考代碼如下:
public ActionResult LoginOut() { System.Web.Security.FormsAuthentication.SignOut(); return RedirectToAction("Login", "Account"); }
- 到此,我們完成了此示例的基本功能模塊,本示例源碼已放置網盤,點此下載。不同用戶登錄系統顯示的頁面結果如下:


