多用户角色权限访问模块问题”的解决思路( 位运算 + ActionFilterAttribute )

如果你还是不太懂位运算,请看我的文章:那些年我们一起遗忘的位运算!

下面是我在这次项目中学习到的,我眼中的位运算的应用!主要是实现 通知的3个操作:

 1.  置顶

 2.  设为首页

 3.  同时为 “置顶”+ “设为首页”

效果如图:

我们要想简便的进行位运算,我们可以直接进行如下枚举定义,以2的次方定义,应为他们的值很特殊:

数      二进制值

1   1 2     10 4       100 8     1000 16     10000 32     100000 64     1000000 128   10000000

复制代码
 /// <summary>
    /// 通知类型
    /// </summary>
    public enum NoticeType
    {
        /// <summary>
        /// 普通
        /// </summary>
        [Description("普通")]
        Normal = 1,
        /// <summary>
        /// 置顶
        /// </summary>
        [Description("置顶")]
        Top = 2,
        /// <summary>
        /// 设置首页
        /// </summary>
        [Description("设置首页")]
        Home = 4,
    }
复制代码

我们就可以很方便的接受参数来进行位运算的操作,代码如下:

复制代码
        /// <summary>
        /// 置顶及设置为首页
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [Role]
        public ActionResult Workshop_NoticeSet(int id, int typeFlag)
        {
            bool res = false;
            Workshop_Notice entity = workshopManager.GetWorkshop_Notice(i => i.WorkshopNoticeID == id);
            if (entity != null)
            {
                switch ((NoticeType)typeFlag)
                {
                    case NoticeType.Home:
                        if ((entity.TypeFlag & (int)NoticeType.Home) > 0)
                            entity.TypeFlag = entity.TypeFlag ^ (int)NoticeType.Home; //取消置顶
                        else
                            entity.TypeFlag = entity.TypeFlag | (int)NoticeType.Home; //置顶
                        break;
                    case NoticeType.Top:
                        if ((entity.TypeFlag & (int)NoticeType.Top) > 0)
                            entity.TypeFlag = entity.TypeFlag ^ (int)NoticeType.Top;  //取消设为首页
                        else
                            entity.TypeFlag = entity.TypeFlag | (int)NoticeType.Top; //设为首页
                        break;
                }
                if (workshopManager.EditWorkshop_Notice(i => new Workshop_Notice
                {
                    TypeFlag = entity.TypeFlag,
                    WorkshopNoticeID = entity.WorkshopNoticeID,
                }).IsComplete)
                    res = true;
            }
            return Content(res.ToString());
        }
复制代码

此项目需求就是根据给用户分配的权限,进行相应的权限模块浏览功能,因为项目不是很大,所以权限没有去用一张表去存,我的解决思路如下,希望大家给点建议。

数据库用户表结构如下

 

数据库表梳理:

BankUserMember:权限分配表(1-省行管理员, 2-分行管理员, 0-网点负责人(普通会员),4-超级管理员)。

      BankUserInfo: 用户详细表。

          BankAgent: 机构层级表。

 用户权限枚举表如下

复制代码
  /// <summary>
    /// 用户角色
    /// </summary>
    public enum Role
    {
        /// <summary>
        /// 注册会员
        /// </summary>
        Member = 0,
        /// <summary>
        /// 省行管理员
        /// </summary>
        ProvinceManager = 1,
        /// <summary>
        /// 分行管理员
        /// </summary>
        BranchManager = 2,
        /// <summary>
        /// 总行管理员
        /// </summary>
        Manager = 3,
        /// <summary>
        /// 超级管理员
        /// </summary>
        SuperManager = 4
  }
复制代码

  普通会员查看功能如下代码

复制代码
    /// <summary>
    /// 会员产看功能
    /// </summary>
    [Role(Entity.Enum.Role.Member)]
    public class PerformanceController : BaseController
    {
        [NoCache]
        public ActionResult Index(int? page)
        {            //todo:
        } 
    }
复制代码

    (省行,分行)管理员查看功能如下代码:

复制代码
 /// <summary>
    /// (省行,分行)管理员查看功能
    /// </summary>
    [Role(Entity.Enum.Role.ProvinceManager | Entity.Enum.Role.BranchManager)]
    public class AdminPerformanceController : BaseController
    {
        [NoCache]
        public ActionResult Index(int? page)
        {            //todo:
        }
    }
复制代码

   权限 RoleAttribute过滤器 如下代码:

复制代码
 /// <summary>
    /// Action角色访问控制
    /// </summary>
    public class RoleAttribute : ActionFilterAttribute
    {
        /// <summary>
        /// 控制角色
        /// </summary>
        public Entity.Enum.Role _role { get; set; }
        /// <summary>
        /// 登录角色
        /// </summary>
        public int memberLoginRole = 0;

        public RoleAttribute() { }
        /// <summary>
        /// 验证方式和角色进行构造
        /// </summary>
        /// <param name="flag"></param>
        public RoleAttribute(Entity.Enum.Role role)
        {
            _role = role;
        }

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (!CheckRole())
            {
                string urlreffer = filterContext.HttpContext.Request.UrlReferrer == null ? string.Empty                                             : filterContext.HttpContext.Request.UrlReferrer.AbsoluteUri;
                if (string.IsNullOrEmpty(urlreffer))
                    urlreffer = filterContext.HttpContext.Request.Url == null ? string.Empty : filterContext.HttpContext.Request.Url.AbsoluteUri;

                string locationUrl = string.Empty;
                locationUrl = TsingDa.Common.WebConfig.GetWebConfig("website_url", "") + "/Home/Login?ReturnUrl=" +                                              filterContext.HttpContext.Server.UrlEncode(urlreffer);
                RedirectResult loginUrl = new RedirectResult(locationUrl);
                filterContext.Result = loginUrl;
            }
            else
            {
                //---------【验证用户的控制器的访问权限利用位运算灵活的解决多角色问题)】---------
                if (((int)_role & (int)memberLoginRole) <= 0 && ((int)_role != memberLoginRole))
                {
                    filterContext.Result = new RedirectResult("/Home/RoleError");
                }
            }

            base.OnActionExecuting(filterContext);
        }

        private bool CheckRole()
        {
            //验证有没有登陆Cookie操作,省略代码。。。。。。。。
         }
    }
复制代码
原文地址:https://www.cnblogs.com/fx2008/p/4281023.html