1. 程式人生 > 其它 >asp.net MVC 許可權設計

asp.net MVC 許可權設計

幾點說明:     1、該許可權系統是個網站用的,使用者簡單,因此不涉及到部門這些資訊     2、基於將角色與controller、action相關聯來判斷使用者是否有權     3、通過過載AuthorizeAttribute實現 資料庫設計:

表說明

ControllerAction

  1.     Name是controller的名稱
  2.     IsController是指是否是controller,如果為false,表示存的是action,那麼controllerName欄位就派上用場了
  3.     IsAllowedNoneRoles是指是否允許沒有許可權的人訪問
  4.     IsAllowedAllRoles是指是否允許有角色的人訪問

IsAllowedNoneRoles,IsAllowedAllRoles實現了允許所有人訪問以及允許所有註冊使用者訪問:),並且我們約定,IsAllowedNoneRoles具有最高的優先順序,其次是IsAllowedAllRoles,然後才是ControllerActionRole中定義的規則

ControllerActionRole

 IsAllowed表示該action或者controller是否允許訪問,加入表中有兩條記錄 角色 Name ControllName IsAllowed IsController    A Admin Home false false    A Home Null true true      這裡約定分兩個層次來判斷許可權:           第一條記錄:表示A角色不能訪問 Home/admin           第二條記錄:表示A角色可以訪問Controller下的所有方法      到底能不能訪問呢?其實,我們以action為準,如果定義了action,我們直接從action的約定來判斷,因此這裡判斷A不能訪問Home/admin

 其他幾張表一看就明白,不再多說

判斷是否有許可權的設定

    1、獲取controller,action,以及存放在session中的使用者資訊

1 publicclass UserAuthorizeAttribute : AuthorizeAttribute 
 2     {
 3 
 4 publicoverridevoid OnAuthorization(AuthorizationContext filterContext) 
 5       { 
 6           var user = filterContext.HttpContext.Session["CurrentUser"] as User; 
 7           var controller = filterContext.RouteData.Values["controller"].ToString(); 
 8           var action = filterContext.RouteData.Values["action"].ToString(); 
 9           var isAllowed =this.IsAllowed(user, controller, action); 
10 
11 if (!isAllowed) 
12           { 
13               filterContext.RequestContext.HttpContext.Response.Write("無權訪問"); 
14               filterContext.RequestContext.HttpContext.Response.End(); 
15           } 
16 
17       }
18 
19     ……
20 
21 }
22

    2、檢索資料庫ControllerAction表中有沒有Name為第一步中controller 的記錄,如果沒有,我們約定這個controller是不需要進行許可權控制的,如果有的話,進入第三步

   3、前面提到了,我們約定對許可權的控制分為兩個層次,controller和action層次,如果同時定義了,以action為準。因此,我們需要判斷是否在資料庫中有action的記錄,如果有,進入4,無,進入5

1 bool IsAllowed(User user, string controllerName, string actionName) 
 2 { 
 3     var service = ServiceLoader.LoadService<ToySpirit.IToySpiritService.IControllerActionService>(); 
 4 
 5 // 獲取對應的controller 
 6      var controller = service.GetSingleByExpression(c => c.Name == controllerName && c.IsController); 
 7 if (controller !=null) 
 8     { 
 9 // 獲取對應的action 
10          var controllerAction = service.GetSingleByFunc(c => c.Name == actionName && c.IsController ==false&& c.ControllerName == controllerName); 
11 
12 return controllerAction ==null?this.isAllowed(user, controller) : this.isAllowed(user, controllerAction); 
13     } 
14 
15 // 沒有定義controller的許可權,表示無需許可權控制 
16  returntrue; 
17 }
18 
19

4、如果有action的記錄,那麼我們首先判斷controllerAction 拒絕哪些角色訪問,如果使用者有角色在這裡面,很遺憾,就不能訪問了;然後判斷controllerAction 允許哪些角色訪問,如果使用者的角色在這裡面,就可以訪問了

注:這裡很有可能使用者有多個角色,比如A,B,C,如果A不能訪問controllerAction,那麼很遺憾,使用者不能訪問,儘管角色B,C可能可以訪問該controllerAction

5、沒有action的記錄,自然就檢查controller對應的controllerAction 了

程式碼
4、5判斷的程式碼是一樣的,如下:
      privatebool isAllowed(User user, ControllerAction controllerAction) 
        { 
            // 允許沒有角色的:也就是說允許所有人,包括沒有登入的使用者 
if (controllerAction.IsAllowedNoneRoles) 
            { 
                returntrue; 
            } 
            // 允許所有角色:只要有角色,就可以訪問 
if (controllerAction.IsAllowedAllRoles) 
            { 
                return user.Roles.Count >0; 
            } 
            if (user ==null|| user.Roles.Count ==0) 
            { 
                returnfalse; 
            } 
            // 選出action對應的角色 
            var roles = controllerAction.ControllerActionRoles.Select(ca => ca.Role).ToList(); 
            if (roles.Count ==0) 
            { 
                // 角色數量為0,也就是說沒有定義訪問規則,預設允許訪問 
returntrue; 
            } 
            var userHavedRolesids = user.Roles.Select(r => r.ID).ToList(); 
            // 查詢禁止的角色 
            var notAllowedRoles = controllerAction.ControllerActionRoles.FindAll(r => r.IsAllowed ==false).Select(ca => ca.Role).ToList(); 
            if (notAllowedRoles.Count >0) 
            { 
                foreach (Role role in notAllowedRoles) 
                { 
                    // 使用者的角色在禁止訪問列表中,不允許訪問 
if (userHavedRolesids.Contains(role.ID)) 
                    { 
                        returnfalse; 
                    } 
                } 
            } 
            // 查詢允許訪問的角色列表 
            var allowRoles = controllerAction.ControllerActionRoles.FindAll(r => r.IsAllowed).Select(ca => ca.Role).ToList(); 
            if (allowRoles.Count >0) 
            { 
                foreach (Role role in allowRoles) 
                { 
                    // 使用者的角色在訪問的角色列表 
if (userHavedRolesids.Contains(role.ID)) 
                    { 
                        returntrue; 
                    } 
                } 
            } 
            returnfalse; 
        }

使用方法:

建立一個basecontroller,使用我們定義好的UserAuthorize,然後所有的controller繼承basecontroller就可以了

1 ///<summary> 
2 /// 控制基類 
3 ///</summary>
4     [UserAuthorize] 
5 publicabstractclass BaseController : Controller 
6    {}
7 
8 publicclass HomeController : BaseController{}
9

演示:

在controlleraction中新增幾條資料:

根據我們的規則,我們可以知道,未登入的使用者可以訪問Home/Public,其他幾個頁面則不能訪問

我們看對應的Action:

1 publicvoid ViewPage() 
 2        { 
 3            Response.Write("View"); 
 4        } 
 5 publicvoid Public() 
 6        { 
 7            Response.Write("Public"); 
 8        } 
 9 publicvoid Delete() 
10        { 
11            Response.Write("Delete"); 
12        }

訪問Home/Public,如果有許可權,那麼顯示“Public“,否則顯示”無權訪問”

未登入使用者訪問Home/Public,結果符合我們的約定;-)

未登入使用者訪問Home/ViewPage,按約定應該顯示錯誤資訊