C#_MVC 自定義AuthorizeAttribute實現權限管理


隨筆- 28  文章- 31  評論- 16 

 

 

MVC 自定義AuthorizeAttribute實現權限管理

 

在上一節中提到可以使用AuthorizeAttribute進行權限管理:

復制代碼
        [Authorize]
        public ActionResult TestAuthorize()
        { 
            return View();
        }

        [Authorize(Users="test1,test2")]
        public ActionResult TestAuthorize()
        { 
            return View();
        }

        [Authorize(Roles="Admin")]
        public ActionResult TestAuthorize()
        { 
            return View();
        }
復制代碼

但是通常情況下,網站的權限並不是固定不變的,當新增角色或者角色改變時,只能修改每個Action對應的特性,當項目較大時工作量可想而知。幸運的是我們可以重寫AuthorizeAttribute達到自定義的權限管理。新建一個CustomAuthorizeAttribute類,使這個類繼承於AuthorizeAttribute。打開AuthorizeAttribute查看下方法說明,我們只需要重寫AuthorizeCore和OnAuthorization就能達到我們的目的。

 

復制代碼
// Summary:
        //     When overridden, provides an entry point for custom authorization checks.
        //
        // Parameters:
        //   httpContext:
        //     The HTTP context, which encapsulates all HTTP-specific information about
        //     an individual HTTP request.
        //
        // Returns:
        //     true if the user is authorized; otherwise, false.
        //
        // Exceptions:
        //   System.ArgumentNullException:
        //     The httpContext parameter is null.
        protected virtual bool AuthorizeCore(HttpContextBase httpContext);


//
        // Summary:
        //     Called when a process requests authorization.
        //
        // Parameters:
        //   filterContext:
        //     The filter context, which encapsulates information for using System.Web.Mvc.AuthorizeAttribute.
        //
        // Exceptions:
        //   System.ArgumentNullException:
        //     The filterContext parameter is null.
        public virtual void OnAuthorization(AuthorizationContext filterContext);
復制代碼

 

 

CustomAuthorizeAttribute重載AuthorizeCore方法,它的處理邏輯如下:首先判斷當前賬戶是否被認證,如果沒有,則返回false;然后獲取當前賬戶的類型,並跟給定的類型進行比較,如果類型相同,則返回true,否則返回false。一般網站中權限管理都會使用權限樹,然后將角色的權限保存至數據庫或者文件中,本例中我們使用XML文件保存每個Action的角色,這樣在用戶請求Action時,由XML文件獲取Action對應的權限,然后檢測賬戶是否有相應的權限。CustomAuthorizeAttribute類的代碼如下:

 

復制代碼
public class CustomAuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
    {
        public new string[] Roles { get; set; }
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (httpContext == null) {
                throw new ArgumentNullException("HttpContext");
            }
            if (!httpContext.User.Identity.IsAuthenticated) {
                return false;
            }
            if (Roles == null) {
                return true;
            }
            if (Roles.Length == 0)
            {
                return true;
            }
            if (Roles.Any(httpContext.User.IsInRole))
            {
                return true;
            }
            return false;
        }

        public override void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext)
        {
            string controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
            string actionName = filterContext.ActionDescriptor.ActionName;
            string roles = GetRoles.GetActionRoles(actionName, controllerName);
            if (!string.IsNullOrWhiteSpace(roles)) {
                this.Roles = roles.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
            }
            base.OnAuthorization(filterContext);
        }
    }
復制代碼

 

當用戶請求一個Action時,會調用OnAuthorization方法,該方法中GetRoles.GetActionRoles(actionName, controllerName);根據Controller和Action去查找當前Action需要具有的角色類型,獲得Action的Roles以后,在AuthorizeCore中與用戶的角色進行比對Roles.Any(httpContext.User.IsInRole),如果沒有相應權限則返回false,程序就會自動跳轉到登錄頁面

 

GetRoles為XML解析類,代碼如下:

 
               
復制代碼
   public class GetRoles
    {
       
        public static string GetActionRoles(string action, string controller) {
            XElement rootElement = XElement.Load(HttpContext.Current.Server.MapPath("/")+"ActionRoles.xml");
            XElement controllerElement = findElementByAttribute(rootElement, "Controller", controller);
            if (controllerElement != null)
            {
                XElement actionElement = findElementByAttribute(controllerElement, "Action", action);
                if (actionElement != null)
                {
                    return actionElement.Value;
                }
            }
            return "";
        }

        public static XElement findElementByAttribute(XElement xElement,string tagName, string attribute)
        {
            return xElement.Elements(tagName).FirstOrDefault(x => x.Attribute("name").Value.Equals(attribute,StringComparison.OrdinalIgnoreCase));
        }
    }
復制代碼

 

相應的權限XMl文件:

 

復制代碼
<?xml version="1.0" encoding="utf-8" ?>
<Roles>
    <Controller name="Home">
        <Action name="Index"></Action>
        <Action name="About">Manager,Admin</Action>
        <Action name="Contact">Admin</Action>
    </Controller>
</Roles>
復制代碼

 

當需求發生變化時,只需要修改XML文件即可

使用時,只需要在Global.asax中注冊該filter

filters.Add(new CustomAuthorizeAttribute());

 

當然這只是一個簡單的例子,實際應用中會復雜許多,還可能要實現在即的MemberShipProvider和RoleProvider


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM