ASP.NET MVC許可權驗證 封裝類

weixin_33816946發表於2015-10-25

 

寫該許可權類主要目地

為了讓許可權配置更加的靈活,可以根據SQL、json、或者XML的方式來動態進行頁面的訪問控制,以及沒有許可權的相關跳轉。

 

使用步驟

 

1、要建一個全域性過濾器

   //受權過濾器
    public class AuthorizeFilter : AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        { 
        }
   }

  

2、Gobal裡註冊 GlobalFilters.Filters.Add(new AuthorizeFilter());該過該全域性過濾器

    protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            GlobalFilters.Filters.Add(new AuthorizeFilter());
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }

  

3、在過濾器中呼叫 SystemAuthorizeService.Start實現

 

   (1)使用物件進行許可權驗證




 public override void OnAuthorization(AuthorizationContext filterContext)
        {
           
            List<SystemAuthorizeModel> smList = new List<SystemAuthorizeModel>()
            {
                //使用者1,2,3可以訪問 area為admin  所有許可權
                new SystemAuthorizeModel() { SystemAuthorizeType= SystemAuthorizeType.Area, AreaName="admin" , UserKeyArray=new dynamic[] { 1,2,3 /*使用者授權陣列*/} },


                //使用者8,7可以訪問 area為admin  控制器為:center   所有許可權
                new SystemAuthorizeModel() { SystemAuthorizeType= SystemAuthorizeType.Controller, AreaName="admin" , ControllerName="center", UserKeyArray=new dynamic[] { 8,7 /*使用者授權陣列*/} },

                
                //使用者1可以訪問為 area為:null 控制器為:home  操作為:about 的請求
                new SystemAuthorizeModel() { SystemAuthorizeType= SystemAuthorizeType.Action,  ControllerName="home" , ActionName="about" , UserKeyArray=new dynamic[] { 1 } },


                //給使用者100和110所有頁面許可權
                new SystemAuthorizeModel() { SystemAuthorizeType= SystemAuthorizeType.All, UserKeyArray=new dynamic[] { 100,110 } }

            };


            SystemAuthorizeErrorRedirect sr = new SystemAuthorizeErrorRedirect();
            sr.DefaultUrl = "/user/login";//沒有許可權都跳轉到DefaultUrl
           //sr.ItemList=xx 設定更詳細的跳轉


            SystemAuthorizeService.Start(filterContext, smList, sr, () =>
            {

                //獲取使用者ID 
                return 1; //使用者ID為1,作為DEMO寫死 ,當然了可以是SESSION也可以是COOKIES等 這兒就不解釋了
            });
        }

  

(2)使用JSON轉成物件進行驗證

[
{
"SystemAuthorizeType": 1,
"AreaName": "admin",
"ControllerName": "center",
"ActionName": null,
"UserKeyArray": [
1,
2,
3
]
},
{
"SystemAuthorizeType": 1,
"AreaName": "admin",
"ControllerName": "center",
"ActionName": null,
"UserKeyArray": [
8,
7
]
},
{
"SystemAuthorizeType": 3,
"AreaName": null,
"ControllerName": "home",
"ActionName": "about",
"UserKeyArray": [
1
]
},
{
"SystemAuthorizeType": 0,
"AreaName": null,
"ControllerName": null,
"ActionName": null,
"UserKeyArray": [
100,
110
]
}
]



SystemAuthorizeService程式碼:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace Idea.Models.Filters
{
    /// <summary>
    /// 系統授權服務
    /// 作者:sunkaixuan
    /// 時間:2015-10-25
    /// </summary>
    public class SystemAuthorizeService
    {
        /// <summary>
        /// 啟動系統授權
        /// </summary>
        /// <param name="filterContext"></param>
        /// <param name="SystemAuthorizeList">所有驗證項</param>
        /// <param name="errorRediect">沒有許可權跳轉地址</param>
        /// <param name="GetCurrentUserId">獲取當前使用者ID</param>
        public static void Start(AuthorizationContext filterContext, List<SystemAuthorizeModel> systemAuthorizeList, SystemAuthorizeErrorRedirect errorRediect, Func<object> GetCurrentUserKey)
        {


            if (errorRediect == null)
            {
                throw new ArgumentNullException("SystemAuthorizeService.Start.errorRediect");
            }
            if (systemAuthorizeList == null)
            {
                throw new ArgumentNullException("SystemAuthorizeService.Start.systemAuthorizeList");
            }

            //全部小寫
            foreach (var it in systemAuthorizeList)
            {
                it.ControllerName = it.ControllerName.ToLower();
                it.ActionName = it.ActionName.ToLower();
                it.AreaName = it.AreaName.ToLower();
            }


            //聲名變數
            var context = filterContext.HttpContext;
            var request = context.Request;
            var response = context.Response;
            string actionName = filterContext.ActionDescriptor.ActionName.ToLower();
            string controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName.ToLower();
            string areaName = null;
            bool isArea = filterContext.RouteData.DataTokens["area"] != null;


            //變數賦值
            if (isArea)
                areaName = filterContext.RouteData.DataTokens["area"].ToString().ToLower();


            //函式方法
            #region 函式方法
            Action<string, string, string> Redirect = (action, controller, area) =>
            {
                filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = controller, action = action, area = area }));
            };
            Action<string> RedirectUrl = url =>
            {
                filterContext.Result = new RedirectResult(url);
            };
            #endregion


            Func<SystemAuthorizeErrorRedirectItemList, bool> redirectActionExpression = it => it.SystemAuthorizeType == SystemAuthorizeType.Action && it.Area == areaName && it.Controller == controllerName && it.Action == actionName;
            Func<SystemAuthorizeErrorRedirectItemList, bool> redirectControllerExpression = it => it.SystemAuthorizeType == SystemAuthorizeType.Action && it.Area == areaName && it.Controller == controllerName;
            Func<SystemAuthorizeErrorRedirectItemList, bool> redirectAreaExpression = it => it.SystemAuthorizeType == SystemAuthorizeType.Action && it.Area == areaName;


            Func<SystemAuthorizeModel, bool> actionExpression = it => it.SystemAuthorizeType == SystemAuthorizeType.Action && it.AreaName == areaName && it.ControllerName == controllerName && it.ActionName == actionName;
            Func<SystemAuthorizeModel, bool> controllerExpression = it => it.SystemAuthorizeType == SystemAuthorizeType.Controller && it.AreaName == areaName && it.ControllerName == controllerName;
            Func<SystemAuthorizeModel, bool> areaExpression = it => it.SystemAuthorizeType == SystemAuthorizeType.Area && it.AreaName == areaName;

            dynamic userId = GetCurrentUserKey();

            //所有許可權
            bool isAllByUuserKey = IsAllByUserKey(systemAuthorizeList, userId);
            bool isAreaByUserKey = IsAreaByUserKey(systemAuthorizeList, areaName, userId);
            bool isControllerByUserKey = IsControllerByUserKey(systemAuthorizeList, areaName, controllerName, userId);
            bool isActionByUserKey = IsActionByUserKey(systemAuthorizeList, areaName, controllerName, actionName, userId);
            //有許可權
            var hasPower = (isAllByUuserKey || isActionByUserKey || isControllerByUserKey || isAreaByUserKey);
            //需要驗證
            var mustValidate = systemAuthorizeList.Any(actionExpression) || systemAuthorizeList.Any(controllerExpression) || systemAuthorizeList.Any(areaExpression);

            if (!hasPower && mustValidate)
            {
                ErrorRediect(errorRediect, RedirectUrl, redirectActionExpression, redirectControllerExpression, redirectAreaExpression);
            }

        }

        private static void ErrorRediect(SystemAuthorizeErrorRedirect errorRediect, Action<string> RedirectUrl, Func<SystemAuthorizeErrorRedirectItemList, bool> actionExpression, Func<SystemAuthorizeErrorRedirectItemList, bool> controllerExpression, Func<SystemAuthorizeErrorRedirectItemList, bool> areaExpression)
        {
            if (errorRediect.ItemList == null)
            {//返回預設錯誤地址
                RedirectUrl(errorRediect.DefaultUrl);
            }
            else if (errorRediect.ItemList.Any(actionExpression))
            {
                var red = errorRediect.ItemList.Single(actionExpression);
                RedirectUrl(red.ErrorUrl);
            }
            else if (errorRediect.ItemList.Any(controllerExpression))
            {
                var red = errorRediect.ItemList.Single(controllerExpression);
                RedirectUrl(red.ErrorUrl);
            }
            else if (errorRediect.ItemList.Any(areaExpression))
            {
                var red = errorRediect.ItemList.Single(areaExpression);
                RedirectUrl(red.ErrorUrl);
            }
            else if (errorRediect.ItemList.Any(it => it.SystemAuthorizeType == SystemAuthorizeType.All))
            {
                var red = errorRediect.ItemList.Single(it => it.SystemAuthorizeType == SystemAuthorizeType.All);
                RedirectUrl(red.ErrorUrl);
            }
            else
            {
                RedirectUrl(errorRediect.DefaultUrl);
            }
        }

        private static bool IsAllByUserKey(List<SystemAuthorizeModel> systemAuthorizeList, object userKey)
        {
            var hasAll = systemAuthorizeList.Any(it => it.SystemAuthorizeType == SystemAuthorizeType.All);
            if (hasAll)
            {
                if (systemAuthorizeList.Any(it => it.UserKeyArray != null && it.UserKeyArray.Contains(userKey)))
                {
                    return true;
                }
            }

            return false;
        }
        private static bool IsAreaByUserKey(List<SystemAuthorizeModel> systemAuthorizeList, string area, object userKey)
        {

            if (systemAuthorizeList.Any(it => it.AreaName == area && it.SystemAuthorizeType == SystemAuthorizeType.Area)) //是否存在驗證級別為Area的驗證
            {
                var isContains = systemAuthorizeList.Any(it => it.AreaName == area && it.SystemAuthorizeType == SystemAuthorizeType.Area && it.UserKeyArray.Contains(userKey));
                return isContains;
            }
            return false;
        }


        private static bool IsControllerByUserKey(List<SystemAuthorizeModel> systemAuthorizeList, string area, string controller, object userKey)
        {
            if (systemAuthorizeList.Any(it => it.AreaName == area && it.ControllerName == controller && it.SystemAuthorizeType == SystemAuthorizeType.Controller)) //是否存在驗證級別為Controller的驗證
            {
                var isContains = systemAuthorizeList.Any(it => it.AreaName == area && it.ControllerName == controller && it.SystemAuthorizeType == SystemAuthorizeType.Controller && it.UserKeyArray.Contains(userKey));
                return isContains;
            }
            return false;
        }




        private static bool IsActionByUserKey(List<SystemAuthorizeModel> systemAuthorizeList, string area, string controller, string action, dynamic userKey)
        {

            if (systemAuthorizeList.Any(it => it.AreaName == area && it.ControllerName == controller && it.ActionName == action && it.SystemAuthorizeType == SystemAuthorizeType.Action)) //是否存在驗證級別為action的驗證
            {
                return systemAuthorizeList.Any(it => it.AreaName == area && it.ControllerName == controller && it.ActionName == action && it.SystemAuthorizeType == SystemAuthorizeType.Action && it.UserKeyArray.ToString().Contains(userKey.ToString()));
            }

            return false;
        }
    }






    /// <summary>
    /// 使用者訪問需要授權的項
    /// </summary>
    public class SystemAuthorizeModel
    {
        /// <summary>
        /// 驗證型別
        /// </summary>
        public SystemAuthorizeType SystemAuthorizeType { get; set; }
        /// <summary>
        /// 使用者擁有許可權訪問的Area
        /// </summary>
        public string AreaName { get; set; }
        /// <summary>
        /// 使用者擁有許可權訪問的Controller
        /// </summary>
        public string ControllerName { get; set; }
        /// <summary>
        /// 使用者擁有許可權訪問的Actioin
        /// </summary>
        public string ActionName { get; set; }
        /// <summary>
        /// 使用者ID
        /// </summary>
        public dynamic[] UserKeyArray { get; set; }

    }

    /// <summary>
    /// 如果沒有許可權返回地址
    /// </summary>
    public class SystemAuthorizeErrorRedirect
    {
        /// <summary>
        /// 預設值
        /// </summary>
        public string DefaultUrl { get; set; }

        public List<SystemAuthorizeErrorRedirectItemList> ItemList { get; set; }
    }

    public class SystemAuthorizeErrorRedirectItemList
    {
        /// <summary>
        /// 驗證型別
        /// </summary>
        public SystemAuthorizeType SystemAuthorizeType { get; set; }
        public string Controller { get; set; }
        public string Action { get; set; }
        public string Area { get; set; }

        public string ErrorUrl { get; set; }

    }

    /// <summary>
    /// 驗證型別
    /// </summary>
    public enum SystemAuthorizeType
    {
        /// <summary>
        /// 所有許可權
        /// </summary>
        All = 0,
        /// <summary>
        ///驗證Area
        /// </summary>
        Area = 1,
        /// <summary>
        /// 驗證Area和Controller
        /// </summary>
        Controller = 2,
        /// <summary>
        /// 驗證Area和Controller和Action
        /// </summary>
        Action = 3,
        /// <summary>
        /// 沒有許可權
        /// </summary>
        No = 4

    }
}

  

相關文章