權(quán)限管理,一般指根據(jù)系統(tǒng)設(shè)置的安全規(guī)則或者安全策略,用戶可以訪問(wèn)而且只能訪問(wèn)自己被授權(quán)的資源,不多不少。權(quán)限管理幾乎出現(xiàn)在任何系統(tǒng)里面,只要有用戶和密碼的系統(tǒng)。權(quán)限管理還是比較復(fù)雜的,有的固定到某個(gè)模塊,某個(gè)操作,甚至是某個(gè)按鈕,總之想要做好一個(gè)權(quán)限管理,真的很不容易,一直在探索當(dāng)中,全當(dāng)拋磚引玉;看到網(wǎng)上好多關(guān)于權(quán)限管理的文章,以前也寫(xiě)過(guò)簡(jiǎn)單的文章,今天樓主我也要總結(jié)整理一下自己的實(shí)現(xiàn)方法,畢竟一千個(gè)讀者就有一千個(gè)哈姆雷特,說(shuō)說(shuō)自己的詳細(xì)實(shí)現(xiàn)、基本設(shè)計(jì)和基本思想希望幫到入門(mén)的新人們。

    一、基本的數(shù)據(jù)庫(kù)表設(shè)計(jì)

      基本的表設(shè)計(jì)如圖,用戶表、角色表、模塊表、權(quán)限表和用戶角色關(guān)系表、角色模塊權(quán)限關(guān)系表,某個(gè)用戶的角色(管理員、用戶等),然后再去判斷對(duì)應(yīng)角色的模塊(新聞、文章等)權(quán)限(增、刪、改、查)。

大學(xué)生就業(yè)培訓(xùn),高中生培訓(xùn),在職人員轉(zhuǎn)行培訓(xùn),企業(yè)團(tuán)訓(xùn)

      創(chuàng)建基本權(quán)限操作的SQL腳本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
CREATE TABLE [dbo].[Module](
    [ID] [int] IDENTITY(1,1) PRIMARY KEY NOT NULL,
    [ModuleKey] [nvarchar](100) NOT NULL,
    [ModuleName] [nvarchar](100) NOT NULL,
)
 
CREATE TABLE [dbo].[Permission](
    [ID] [int] IDENTITY(1,1) PRIMARY KEY NOT NULL,
    [PermissionKey] [nvarchar](100) NOT NULL,
    [PermissionName] [nvarchar](100) NOT NULL,
)
 
CREATE TABLE [dbo].[Role](
    [ID] [int] IDENTITY(1,1) PRIMARY KEY NOT NULL,
    [RoleName] [nvarchar](100) NOT NULL,
)
 
CREATE TABLE [dbo].[RoleModulePermission](
    [ID] [int] IDENTITY(1,1) PRIMARY KEY NOT NULL,
    [RoleID] [intNOT NULL,
    [ModuleID] [intNOT NULL,
    [PermissionID] [intNOT NULL,
)
 
CREATE TABLE [dbo].[User](
    [ID] [int] IDENTITY(1,1) PRIMARY KEY NOT NULL,
    [AccountNum] [nvarchar](100) NOT NULL,
    [Pwd] [nvarchar](100) NOT NULL,
    [Status] [intNOT NULL,
    [LastLoginTime] [datetime] NOT NULL,
    [Remark] [nvarchar](100) NULL,
)
 
CREATE TABLE [dbo].[UserRole](
    [ID] [int] IDENTITY(1,1) PRIMARY KEY NOT NULL,
    [UserID] [intNOT NULL,
    [RoleID] [intNOT NULL,
)

  二、代碼中具體的實(shí)現(xiàn)

      這是一個(gè)基類,所有的Controller都繼承BaseController,[UserAuthorizeFilter(Order = 999)],每一個(gè)Action過(guò)濾器都有一個(gè) Order 屬性,用來(lái)決定Action過(guò)濾器在該范圍內(nèi)的執(zhí)行順序。Order屬性必需是0(默認(rèn)值)或者更大的整數(shù)值。省略O(shè)rder屬性則會(huì)給該過(guò)濾器的Order值為 -1, 表明為指明順序。任何一個(gè)在同一范圍的Action過(guò)濾器Order設(shè)為 -1 的都將按不確定的順序執(zhí)行,單在此之前過(guò)濾器有一個(gè)特定的順序。登錄的時(shí)候是存儲(chǔ)的加密的Cookie,會(huì)有一個(gè)私鑰(自己定義)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
[UserAuthorizeFilter(Order = 999)]
public class BaseController : Controller
{
    public int LoginID { getset; }
    public string LoginName { getset; }
    /// <summary>
    /// 是否登錄的標(biāo)志
    /// </summary>
    /// <returns></returns>
    public bool IsLogin()
    {
        if (NCookieUtil.GetCookie("GkqCMSCookie") != null)
        {
            string cookie_ver = NCookieUtil.GetCookie("GkqCMSCookie");
            string[] cookieArray = cookie_ver.Split('&');
            int loginId = cookieArray[1].ToInt();
            string token = cookieArray[0].ObjectToString();
            Admin_User user = AdminPermissionRepository.Get(loginId);
            if (user != null)
            {
                string tokenKey = string.Format("{0}{1}{2}{3}", user.ID.ObjectToString(), user.AccountNum.ObjectToString(), user.Pwd.ObjectToString(), CommonHelper.SecretSalt);
                if (token == tokenKey)
                {
                    LoginID = user.ID;
                    LoginName = user.AccountNum;
                    return true;
                }
                return false;
            }
            return false;
        }
        else
        {
            return false;
        }
    }
}

  Filter里面判斷用戶是否登錄cb.IsLogin(),如果登陸驗(yàn)證通過(guò)還要驗(yàn)證是否對(duì)某個(gè)某個(gè)Controller對(duì)應(yīng)的Action有操作權(quán)限。如果未登錄或者發(fā)成錯(cuò)誤底層會(huì)捕獲,跳轉(zhuǎn)到登陸頁(yè)面或者是錯(cuò)誤頁(yè)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class UserAuthorizeFilter : System.Web.Mvc.AuthorizeAttribute
   {
       public override void OnAuthorization(AuthorizationContext filterContext)
       {
           BaseController cb = filterContext.Controller as BaseController;
           if (!cb.IsLogin())
           {
               SetHttpContext(filterContext, GkmBBS.DataCenter.GlobalEnumHelper.EnumJsonResult.NotLogin, "未登錄");
           }
           else
           {
               bool IsAuthorization = filterContext.Controller.TempData["IsAuthorization"].ToBoolean(true);
               if (IsAuthorization)
               {
                   string controller = filterContext.RouteData.Values["controller"].ObjectToString();
                   string action = filterContext.RouteData.Values["action"].ObjectToString();
                   if (!AdminPermissionRepository.IsPowerPage(cb.LoginID,controller, action))
                   {
                       SetHttpContext(filterContext, GkmBBS.DataCenter.GlobalEnumHelper.EnumJsonResult.NoAccess, "您沒(méi)有權(quán)限執(zhí)行此操作");
                   }
               }
           }
       }
 
       private void SetHttpContext(AuthorizationContext filterContext, GkmBBS.DataCenter.GlobalEnumHelper.EnumJsonResult result, string msg)
       {
           if (filterContext.HttpContext.Request.IsAjaxRequest())
           {
               var data = new { Result = (int)result, Msg = msg };
               filterContext.Result = new JsonpResult() { Data = data, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
           }
           else
           {
               if (result == GkmBBS.DataCenter.GlobalEnumHelper.EnumJsonResult.NotLogin)
               {
                   filterContext.Result = new RedirectResult(string.Format("/Login/Index?ReturnUrl={0}", filterContext.HttpContext.Request.Url.OriginalString));
               }
               else
               {
                   filterContext.Controller.ViewData["ErrorMessage"] = msg;
                   filterContext.Result = new ViewResult() { ViewName = "Error", ViewData = filterContext.Controller.ViewData };
               }
           }
       }
   }

  用戶的ID判斷角色,然后把角色去查是否有這個(gè)權(quán)限,如果有進(jìn)入,對(duì)應(yīng)的controller 和action,如果沒(méi)有則沒(méi)權(quán)限。具體實(shí)現(xiàn)方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
    public static bool IsPowerPage(int loginID, string Moudle, string operate)
        {
            try
            {
                string sql = string.Format(@"SELECT COUNT(1)
FROM (
           SELECT c.modulekey,
                  d.permissionkey
           FROM   (
                      SELECT *
                      FROM   Admin_userrole
                      WHERE  userid = {0}
                  ) a
                  LEFT JOIN Admin_RoleModulePermission b
                       ON  a.roleId = b.roleId
                  LEFT
           JOIN Admin_Module c
                       ON  b.moduleId = c.Id
                  LEFT JOIN Admin_Permission d
                       ON  b.PermissionId = d.Id
       ) e
WHERE  e.moduleKey = '{1}'
       AND e.PermissionKey = '{2}'", loginID, Moudle, operate);
                return NSqlHelper.ExecuteScalar(NWebConfig.ReadConnectionString(DBCon.SYS_DBCONNSTRING), CommandType.Text, sql, null).ToInt() > 0;
            }
            catch (Exception ex)
            {
                log.Error("AdminPermissionRepository-IsPowerPage", ex);
                return false;
            }
        }

       用戶登錄成功寫(xiě)入Cookie,然后瀏覽每個(gè)模塊判斷登錄和具體某個(gè)模塊的權(quán)限, 這算是一個(gè)最基本簡(jiǎn)單權(quán)限管理,適合新手入門(mén)用,大牛們覺(jué)的不合適的地方,或者更好的方法多多指導(dǎo)!