MVC 自定义AuthorizeAttribute实现权限管理

本文介绍了一种使用ASP.NET MVC框架自定义权限管理的方法,通过创建CustomAuthorizeAttribute类并重写AuthorizeCore和OnAuthorization方法实现。文章详细解释了如何从XML文件读取权限设置并应用于控制器的动作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在上一节中提到可以使用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

功能介绍: 本系统通过对MVC4 Simplemembership默认数据库进行扩展实现了后台管理用户,角色和权限。通过角色的权限配置实现对前台Controller和Action的权限管理。 使用方法: 第一步:修改Web.config文件。 这个文件中只需要TYStudioUsersConnectionString中的用户名和密码,修改为你本地具有创建数据库的权限的用户名和密码。修改完成运行程序会系统会自动创建扩展后的Membership数据库。 第二步:建立系统管理员角色和用户。 考虑到手动添加系统管理员角色和用户比较麻烦,初始的程序都是可以匿名访问的,这时候你需要运行系统添加一个系统管理员角色,并添加一个用户赋给系统管理员权限。再添加完系统管理员角色和用户之后你需要修改一下Controllers下面的各个Controller,注释掉[AllowAnonymous]并把//[Authorize(Roles = "系统管理员")]注释打开。编译重新运行程序,这时后台管理系统只能允许系统管理员角色的用户登陆了。 第三步:测试产品模块(ProductController) Controller下有一个ProductController是用来测试我们的权限管理是否成功的起作用了,同时也是对前台Controller和Action进行全线控制的方法。这里使用[TYStudioAuthorize("查询产品")]方式对Action进行访问控制。所有关于Membership的类都在Models/Membership文件夹下面。将来你需要把这些class移植到你的公共project中去,这样就可以使用MVC4 Simplemembership对你的前台进行权限控制了。 注意: 开发环境为Visual Studio 2012
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值