ASP.NET MVC+EF框架+EasyUI實現權限管系列
(開篇) (1):框架搭建 (2):數據庫訪問層的設計Demo (3):面向接口編程 (4 ):業務邏輯層的封裝
(5):前台Jquery easyUI實現 (6):EF上下文實例管理 (7):DBSession的封裝 (8):DBSession線程內唯一
(9):TT摸版的學習 (10):VSS源代碼管理 (11):驗證碼實現和底層修改 (12):實現用戶異步登錄和T4模板
(13):權限設計 (14):主框架搭建 (15):權限數據庫模型和用戶登錄詳細錯誤 (16):用戶注冊的各種驗證
(17):注冊用戶功能的細節處理 (18):過濾器的使用和批量刪除數據(偽刪除和直接刪除)
(19):用戶信息的修改和瀏覽 (20):多條件模糊查詢和回收站還原的實現 (21):用戶角色權限基本的實現說明
(22):為用戶設置角色 (23):設置角色遺留問題和EasyUI Tabs使用
前言:已經有很長的一段時間沒有寫博客了,主要是這段時間生活有動盪了一下,所以一直沒有顧得過來寫,所以對那些關注我這個系列的博友們說聲對不起,本來打算中途放棄的,因為后面的東西實在不好寫,重點是說了很多,但是博友們看不明白,在好幾個類庫以及控制器和實體之間轉換導致了這樣的結果,但是自己一想干一件事情我們就一定要干完,所以我會堅持寫完這個系列的,這幾天抽空出來,所以繼續我們權限系列的步伐,希望大家能夠支持我,謝謝,如果大家想去下載次項目練習版本的話,可以去百度搜索:《ASP.NET MVC+EF框架+EasyUI實現權限管理源碼》下載學習,此版本只適用於學習,和現在寫的項目的版本基本不一樣,希望大家能夠對比學習。
那么今天我們就開始講述權限組的實現和設計吧。
1. 為什么要有權限組
(1)通過前面的博客我們已經基本上完成了項目的用戶,角色和權限的功能,那么我們現在才出現了權限組,那么我們的權限組是用來干什么的呢?這里我大致說一下,首先看如圖所示的菜單導航:

(2)如上圖所示,我們的菜單導航是靜態寫死在HTML中的,那么這樣的話很不利於我們項目的維護,當我們需要添加一個菜單導航的話,我們只有去HTML中更改了,鑒於上面的需求,所以我們需要將其變化成動態並且存放在數據庫中,那么這時候我們就創建了權限組的數據表來存放這些數據。
2.權限組和權限的關系描述
(1)首先菜單導航應該跟用戶關聯到一塊,這是為什么呢?因為有的用戶可能有后台權限管理,網站基本管理欄目,而有的用戶可能沒有網站基本管理欄目,而超級管理員應該含有所有的欄目,那么這時候我們就想我們的菜單導航的欄目(指的是后台權限管理,網站基本管理,網站開發支持三個欄目分組)怎么跟用戶和權限去關聯呢?因為菜單導航也是跟權限有關系的,那么這時候我們就想我們的菜單組(權限組)怎么去設計。
(2)根據上面的描述我們知道了我們菜單導航中的分組以及子類都要去存放到數據庫中,那么我們怎么設計我們的菜單導航跟權限聯系到一塊呢?
(3)我們知道我們菜單導航(菜單組)里面的數據都對應的有權限,所以我們就要想那么我們的菜單組和菜單項怎么在模型中設計出來,當我們用戶登錄到系統的時候便可以直接拿到菜單組合菜單項的數據展示在菜單導航里面。
3.菜單項和菜單組的實現
(1)可能這里我寫菜單項和菜單組的話部分人會暈,我這里解釋一下,菜單項就是菜單組下面的子節點,比如:菜單組是后台權限管理,而菜單項是后台權限管理下面的子節點。
(2)這樣的話我們下來看我們的這個權限的模型如圖所示:

因為我們在BasePermission表中是對菜單的總體操作,但是我們的菜單又分為菜單組和菜單項,所以這樣的話我們還需要給這個模型中添加一個標識,這個標識的作用就是區分到底是菜單組還是菜單項,用(1,0)標識即可
(3)這樣我們就設計完了菜單項,那么下面我們主要還是討論如何建立菜單項
4.菜單項的實現
(1)那么根據我們上述的描述的話,我們在這里需要建立一個菜單項管理的數據庫,所以我們主要分析一下我們該如何建立這個菜單項的數據庫和這個數據庫和其它的之間的關系。首先我直接上Edmx模型說明這個數據庫和關系,如圖所示:

(2)這里我首先要陳述兩點,那就是菜單組和菜單項是多對多的關系,從我的模型中可以看出了又一個中間表。
(3)菜單組和用戶肯定也是有關系的,那么我們也可以想到用戶和菜單組肯定也是多對多的關系。
(4)那么菜單組和角色之間肯定也是有關系,我們可以想到也是多對多的關系,那么到這里我們的關系就建立完畢了,整個菜單組關聯了所有的項目
(5)如果大家看這個的話我覺得應該看得很模糊,那么我將數據庫的創建的文檔放在了CSDN上面,大家可以去下載:下載地址是:
http://download.csdn.net/detail/hanyinglong/5862727
5.菜單組最終完成
(1)到這里我們的數據庫之類的就都已經建立完畢了,至於怎么建立的,我覺得用過edmx模型的基本都知道,那么這個部分我們就算是完成了,下面展示我們這部分的內容,其實和前面的基本一樣,如圖所示:


(2)那么下篇博客我說一下如何對這些前面所加入的驗證的東西在項目登錄的時候驗證用戶是不是沒有此權限呢。
(3)本項目之前的源碼下載地址如下:
(4)至於如何在他們的中間建立關系,大家去看我的上上篇博客是如何給他們建立關系的,我們后續的幾個關系我也就不說了,下篇博客可能要到下周才能寫,我將些我們如何判斷用戶登錄進來顯示的內容。
(5)后續思路的實現(這個系列就終結了,希望大家理解):
因為當時有事,所以這個系列就擱置了,后來時間長了就懶得去寫了,所以這里給大家說一下后面的思路,現在前面所以的鋪墊都已經做完了,后面如何查詢出該有的頁面則很簡單了。
(1):首先寫一個過濾器,當用戶手動輸入網址的時候進行判斷這個網址是否該用戶允許訪問,不允許則直接跳轉黃頁,允許則直接跳轉到操作頁面
(2):然后TreeNode的實現
第一步:根據登錄的用戶查詢到角色對應的權限(權限含有頁面)
第二步:根據登錄的用戶查詢到對應的權限(權限含有頁面)
第三步:將第一步和第二步進行Union ALL去除重復則可以直接拿到該用戶需要看到的頁面
第四步:使用遞歸TreeNode進行循環顯示即可。遞歸的用戶如果大家不會的話去百度一下一大把~~~~
(6)大部分同學問我說我輸入地址之后如何判斷用戶是否登錄以及用戶是否有訪問該地址的權限,下面我將大綱代碼貼出來,大家看看,代碼如下:
//讀取當前用戶的Session信息
protected ExtendUserInfo UserInfo
{
get
{ //從緩存中獲取登錄的信息
return ContextHelper.GetCurrentUser();
}
}
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
//拿到Session信息
// UserInfo = Session["UserInfo"] as ExtendUserInfo;
if (UserInfo == null)
{
Response.Redirect("/Login/Index");
}
//判斷路勁某個人是否能夠訪問:構造查詢判斷登錄的用戶能夠訪問此時刷新的路勁
}
6.此項目中封裝的使用T_SQL語句和存儲過程的方法
/// <summary> /// 執行SQL對象返回受影響的行數 /// </summary> /// <param name="strSql">SQL語句</param> /// <param name="parameters">參數</param> /// <returns></returns> public int ExcuteSql(string strSql, object[] parameters) { return EFContextFactory.GetCurrentDbContext().Database.ExecuteSqlCommand(strSql, parameters); } /// <summary> /// 執行SQL對象,返回查詢到的實體集合 /// </summary> /// <typeparam name="T">返回的實體集合</typeparam> /// <param name="strSql">SQL語句</param> /// <param name="parameters">傳遞的參數</param> /// <returns></returns> public IQueryable<T> ExecuteSql<T>(string strSql, object[] parameters) { return EFContextFactory.GetCurrentDbContext().Database.SqlQuery<T>(strSql, parameters).AsQueryable(); } /// <summary> /// 執行SQL對象,返回查詢到的實體集合 /// </summary> /// <typeparam name="T">返回的實體集合</typeparam> /// <param name="strSql">SQL語句</param> /// <returns></returns> public IQueryable<T> ExecuteSql<T>(string strSql) { return EFContextFactory.GetCurrentDbContext().Database.SqlQuery<T>(strSql).AsQueryable(); } /// <summary> /// 執行存儲過程,返回查詢到的實體集合 /// </summary> /// <typeparam name="T">返回的實體集合</typeparam> /// <param name="procSql">存儲過程</param> /// <param name="parameters">參數</param> /// <returns></returns> public IQueryable<T> ExexuteProc<T>(string procSql, object[] parameters) { return EFContextFactory.GetCurrentDbContext().Database.SqlQuery<T>(procSql, parameters).AsQueryable(); } /// <summary> /// 執行存儲過程,返回查詢到的實體集合 /// </summary> /// <typeparam name="T">返回的實體集合</typeparam> /// <param name="procSql">存儲過程</param> /// <returns></returns> public IQueryable<T> ExexuteProc<T>(string procSql) { return EFContextFactory.GetCurrentDbContext().Database.SqlQuery<T>(procSql).AsQueryable(); } /// <summary> /// 執行SQL對象返回受影響的行數 /// </summary> /// <param name="procSql">SQL語句</param> /// <param name="parameters">參數</param> /// <returns></returns> public int ExcuteProc(string procSql, object[] parameters) { return EFContextFactory.GetCurrentDbContext().Database.ExecuteSqlCommand(procSql, parameters); }
7.源碼下載
(1):完整源碼下載
Kencery返回本系列開篇
