• 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文件即可

    使用时,只需要在FilterConfig中注册该filter

    filters.Add(new CustomAuthorizeAttribute());

    当然这只是一个简单的例子,实际应用中会复杂许多,还可能要实现在即的MemberShipProvider和RoleProvider

  • 相关阅读:
    AppDomain应用及 如何改变web.config / App.config位置
    WPF 值转换器 IValueConverter 例子
    ICSharpCode.SharpZipLib .dll 使用说明
    Unity 概述
    MySQL速度变慢,怎么办?【转载】
    微软企业库 Enterprise Library
    MySql 慢查询设置 和 查看
    Prism 概述
    使用SSH Secure Shell登陆Linux出现乱码的解决
    RHEL5 YUM安装GCC
  • 原文地址:https://www.cnblogs.com/sjqq/p/7286138.html
Copyright © 2020-2023  润新知