欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

ASP.NET MVC权限控制思路

程序员文章站 2022-04-06 08:20:23
在系统开发的时候一个老生常谈的权限管理问题,翻阅了很多的网络资料,但是总感觉离实际使用还有一段距离,其实权限控制无非就几个“请求、页面按钮、字段显示”, 对于前端权限就需要配合JS了, 这里主要展示我这些年来一直使用的一个关于权限管理的案例,如果你只是写一个简单的CMS系统,那么下面代码其实拷贝就可 ......

在系统开发的时候一个老生常谈的权限管理问题,翻阅了很多的网络资料,但是总感觉离实际使用还有一段距离,其实权限控制无非就几个“请求、页面按钮、字段显示”, 对于前端权限就需要配合js了, 这里主要展示我这些年来一直使用的一个关于权限管理的案例,如果你只是写一个简单的cms系统,那么下面代码其实拷贝就可以用了,如果是需要进行较大型系统开发就需要进一步封装, 下面是我的思路,写的不好大家勿喷哈,有不同意见的留下一起探讨。

1、在mvc开发时路由中包含了我们所有请求信息(controller、action、url全文),而mvc又提供了过滤器的机制,因此我们将权限管理封装到过滤其中。首先把每个controller的继承封装一个basecontroller,这个controller基类可以编写一些直接调用的方法,例如session等。

    /// <summary>
    /// 系统基础控制器类
    /// </summary>
    public abstract class baseuicontroller : controller
    {
        /// <summary>
        /// 页面初始化过程
        /// </summary>
        protected override void initialize(system.web.routing.requestcontext requestcontext)
        {
            requestcontext.httpcontext.response.cache.setcacheability(httpcacheability.nocache);
            base.initialize(requestcontext);
        }

        /// <summary>
        /// 内容返回
        /// </summary>
        /// <param name="content">特定内容供js参考是否含流程定义等动作。</param>
        /// <param name="contenttype"></param>
        /// <param name="contentencoding"></param>
        /// <returns></returns>
        protected override contentresult content(string content, string contenttype, encoding contentencoding)
        {
            return base.content(content, contenttype, contentencoding);
        }

        /// <summary>
        /// 登陆用户id (session存储)
        /// </summary>
        public long logineduserid
        {
            get
            {
                object uid = ant.ui.controls.sessionconfig.getsession("uid");
                if (session == null || uid == null)
                    return -1;
                else
                {
                    return (long)uid;
                }
            }
            set
            {
                ant.ui.controls.sessionconfig.setsession("uid", value);
            }
        }
        
        /// <summary>
        /// 获取url参数值,返回 null 或 值
        /// </summary>
        /// <param name="keyname">参数名</param>
        public string requesturlparams(string keyname)
        {
            if (array.indexof(request.querystring.allkeys, keyname) >= 0)
                return request.querystring[keyname].tostring();
            else
                return null;
        }
    }

2、这个时候我们编写一个过滤器,在这个过滤器中可以在请求的controller中获取controller名称和action名称。 有了这两个名称就能定位到具体的页面了,当然在得到页面之前我们可以判断用户是否已经登录。而页面权限页已经用数据库保存起来:a用户或r角色对某一个controller/action的页面(这个页面可能是新增信息、修改、删除信息的请求链接)是否有访问权限。

    /// <summary>
    /// 用户登录过滤器
    /// </summary>
    public class userloginedfilter : authorizeattribute
    {
        public string name { get; set; }
        /// <summary>
        /// 页面授权过程(验证用户登录状态)
        /// </summary>
        /// <param name="filtercontext"></param>
        public override void onauthorization(authorizationcontext filtercontext)
        {
            ui.controllers.baseuicontroller _controllerobj = (ui.controllers.baseuicontroller)filtercontext.controller;
            string controllerstr = _controllerobj.controllercontext.routedata.values["controller"].tostring();
            string actionstr = _controllerobj.controllercontext.routedata.values["action"].tostring();
            
            //用户尚未登陆 或 登陆超时。
            if (_controllerobj.logineduserid == -1)
            {
                usererror.loginerror();
            }
            // 权限验证 根据 controller 与 action(这里可以将权限缓存取出来进行用户匹配,如果被拒绝可以抛出异常)
            else if ( controllerstr.tolower() == "admin" && actionstr.tolower() == "login")
            {
                throw new httpexception("权限验证。" + _controllerobj.controllercontext.controller.tostring());
            }

            base.onauthorization(filtercontext);
        }
    }

3、此时页面调用时就不用在每个action中编写权限验证代码啦(有些权限验证的源码会在action上增加过滤器,为了偷懒硬是想方设法把权限封装成直接在controller类上添加一次过滤器就能完成的实现)

    [userloginedfilter]
    public class admincontroller : ui.controllers.baseuicontroller
    {
        /// <summary>
        /// 登陆(登陆页面不需要权限验证,增加allowanonymous特性)
        /// </summary>
        [allowanonymous]
        public actionresult login(formcollection form)
        {
            return view();
        }

        /// <summary>
        /// 主界面
        /// </summary>
        public actionresult index()
        {
            return view();
        }
    }

上面只是我在系统开发过程中对于权限管理的一个思路,也实实在在的应用到了一些系统中,当然上面这些代码只能勉强判断是否登陆,如果你需要对数据权限、页面权限、字段权限进行管理那么就需要进一步的扩展。如果需要在抛出异常后将异常信息友好的返回给客户端,那你仍然需要在global中捕获返回状态码以及错误信息。因此我说这只是我的一个思路,路过的朋友给我建议。多谢!