ASP.NET MVC 巧用代码注释做权限控制以及后台导航

请先看:https://cloud.tencent.com/developer/article/1057566

权限控制需要将控制器和Action信息写入到数据库,手动添加的话比较麻烦,有没有更简单的办法呢?

那就用反射把吧,我们可以借助代码注释( 将权限控制的详细用xml注释的方式写到代码里)+反射技术来巧妙的实现

同时,还可以用来作后台导航哦

效果篇

  /// <IsShow>True</IsShow>   /// <IsHeader>True</IsHeader>   /// <Title>个人信息</Title>   /// <IsAllowedNoneRoles>False</IsAllowedNoneRoles>    /// <IsAllowedAllRoles>False</IsAllowedAllRoles> 

class UserInfoController{}

后台对应的效果

XML注释说明

       /// <IsShow>True</IsShow>   表示是否在导航菜单显示        /// <IsHeader>False</IsHeader>  表示是否是导航标题  通常用于Controler类        /// <Title>选择用户</Title>     标题        /// <IsAllowedNoneRoles>False</IsAllowedNoneRoles>  是否允许匿名访问        /// <IsAllowedAllRoles>False</IsAllowedAllRoles>   是否允许所有登录用户访问

读取XML注释

首先配置MVC项目,生成XML文件 属性 --生成  -- 输出

  在网站启动的时候,执行初始化任务

// 执行启动任务
            IoC.ResolveAll().ForEach(t => t.Execute());

相关代码:

/// 
    /// 启动任务
    /// 
    public interface IBootstrapperTask
    {
        void Execute();
    }

具体实现代码:

public class InitSystemConfig : IBootstrapperTask {
        private readonly IDomainObjectFactory _factory;
        private readonly IUserRepository _userRepository;
        private readonly IRoleRepository _roleRepository;

        private readonly IResourceRepository _resourceRepository;
        private readonly DefaultRole[] _defaultRoles;
        private readonly DefaultUser[] _defaultUsers;
        private readonly DefaultResource[] _defaultResources;

        public InitSystemConfig(IDomainObjectFactory factory, IUserRepository userRepository,
                                IRoleRepository roleRepository, IResourceRepository resourceRepository,
                                DefaultRole[] defaultRoles, DefaultUser[] defaultUsers, DefaultResource[] defaultResources) {
            Check.Argument.IsNotNull(factory, "factory");
            Check.Argument.IsNotNull(userRepository, "userRepository");
            Check.Argument.IsNotNull(roleRepository, "roleRepository");
            Check.Argument.IsNotNull(defaultRoles, "defaultRoles");
            Check.Argument.IsNotNull(defaultUsers, "defaultUsers");

            _factory = factory;
            _userRepository = userRepository;
            _roleRepository = roleRepository;
            _resourceRepository = resourceRepository;

            _defaultRoles = defaultRoles;
            _defaultUsers = defaultUsers;
            _defaultResources = defaultResources;
        }

        public void Execute() {
            CreateResourceIfNotrExist();
            CreateDefaultController();
            CreateRoleIfNotExist();
            CreateUserIfNotrExist();
        }

        ///
        /// 为没有配置信息的控制器和Action创建记录,默认设为所有用户可访问
        ///
        void CreateDefaultController() {
            using (IUnitOfWork unitOfWork = UnitOfWork.Begin()) {
                IConfigurationManager configurationManager = IoC.Resolve();

                var assemblyName = configurationManager.AppSettings["WebAssemblyName"];

                if (string.IsNullOrEmpty(assemblyName)) {
                    assemblyName = "MarkerPlatform.Web";
                }

                Assembly assembly = Assembly.Load(assemblyName);
                Type[] types = assembly.GetTypes();

                var assemblyXml = HttpContext.Current.Server.MapPath("~/bin/" + assemblyName + ".xml");

                XmlDocument assembleDoc = new XmlDocument();

                if (File.Exists(assemblyXml))
                    assembleDoc.Load(assemblyXml);

                foreach (Type type in types) {
                    if (type.BaseType != null) {
                        if (type.Name.Contains("Controller") && type.BaseType.Name == "BaseController") {
                            // 查询数据库有没有controler信息

                            var controllerName = type.Name.Replace("Controller", "");

                            var dbController = _resourceRepository.FindController(controllerName);

                            // controller为空或者允许所有人访问并且不允许匿名用户访问
                            // 如果允许匿名用户访问,则这个控制器默认所有Action均可访问
                            if (dbController == null || dbController.IsAllowedAllRoles && !dbController.IsAllowedNoneRoles) {
                                if (dbController == null) {
                                    // 获取controller
                                    dbController = GetController(assembleDoc, type, controllerName);

                                    if (dbController != null)
                                        _resourceRepository.Add(dbController);
                                }

                                //获取方法信息
                                MethodInfo[] myMethodInfo = type.GetMethods();

                                try {
                                    foreach (var methodInfo in myMethodInfo) {
                                        if (methodInfo.ReturnType.Name == "ActionResult") {
                                            var actionName = methodInfo.Name;

                                            var dbresource = _resourceRepository.FindAction(controllerName, actionName);

                                            if (dbresource == null) {
                                                // 默认设为所有用户可访问
                                                dbresource = GetDbresource(assembleDoc, controllerName, methodInfo, actionName);

                                                if (dbresource != null)
                                                    _resourceRepository.Add(dbresource);
                                            }
                                        }
                                    }
                                }
                                catch (Exception ex) {

                                    Console.Write(ex);
                                }
                            }
                        }
                    }
                }

                unitOfWork.Commit();
            }
        }


        ///
        /// 为方法创建实体
        ///
        ///
        ///
        ///
        ///
        ///
        private IResource GetDbresource(XmlDocument assembleDoc, string controllerName, MethodInfo methodInfo, string actionName) {
            IResource dbresource;

            dbresource = _factory.CreateResource(actionName, controllerName,
                                                 false,
                                                 false,
                                                 true);
            var path = "M:" + methodInfo.DeclaringType.FullName + "." + methodInfo.Name;

            XmlNode node = GetNode(assembleDoc, path);

            if (node == null) {
                dbresource.IsHeader = false;
                dbresource.IsShow = false;
                dbresource.Title = controllerName + "/" + actionName;
            }
            else {
                var child = node.SelectSingleNode("IsShow");
                dbresource.IsShow = child != null && bool.Parse(child.InnerText);

                child = node.SelectSingleNode("IsHeader");
                dbresource.IsHeader = child != null && bool.Parse(child.InnerText);

                child = node.SelectSingleNode("Title");

                if (child == null)
                    child = node.SelectSingleNode("summary");

                dbresource.Title = child != null ? child.InnerText.Trim() : "";

                if (string.IsNullOrEmpty(dbresource.Title)) {
                    dbresource.Title = controllerName + "/" + actionName;
                }

                child = node.SelectSingleNode("IsAllowedAllRoles");
                dbresource.IsAllowedAllRoles = child != null && bool.Parse(child.InnerText);

                child = node.SelectSingleNode("IsAllowedNoneRoles");
                dbresource.IsAllowedNoneRoles = child != null && bool.Parse(child.InnerText);
            }
            return dbresource;
        }


        ///
        /// 为控制器创建实体
        ///
        ///
        ///
        ///
        /// 
        private IResource GetController(XmlDocument assembleDoc, Type type, string controllerName) {
            IResource dbController;
            XmlNode controllerNode = GetNode(assembleDoc, "T:" + type.FullName);


            // 默认匿名用户不能访问  登录用户均可访问
            dbController = _factory.CreateResource(controllerName, controllerName, true, false,
                                                   true);

            if (controllerNode != null) {
                var child = controllerNode.SelectSingleNode("IsShow");

                dbController.IsShow = child != null && bool.Parse(child.InnerText);

                child = controllerNode.SelectSingleNode("IsShow");
                dbController.IsHeader = child != null && bool.Parse(child.InnerText);

                child = controllerNode.SelectSingleNode("Title");
                if (child == null)
                    child = controllerNode.SelectSingleNode("summary");
                dbController.Title = child != null ? child.InnerText.Trim() : "";

                if (string.IsNullOrEmpty(dbController.Title.Trim())) {
                    dbController.Title = controllerName;
                }

                child = controllerNode.SelectSingleNode("IsAllowedAllRoles");
                dbController.IsAllowedAllRoles = child != null && bool.Parse(child.InnerText);

                child = controllerNode.SelectSingleNode("IsAllowedAllRoles");
                dbController.IsAllowedAllRoles = child != null && bool.Parse(child.InnerText);

            }
            else {
                dbController.IsHeader = false;
                dbController.IsShow = false;
                dbController.Title = controllerName;
            }
            return dbController;
        }


        private XmlNode GetNode(XmlDocument assembleDoc, string name) {
            var nodes = assembleDoc.SelectNodes("/doc/members/member");

            XmlNode node = null;

            if (nodes != null)
                foreach (XmlNode xmlNode in nodes) {
                    if (xmlNode.Attributes != null)
                        if (xmlNode.Attributes["name"].Value.Contains((name))) {
                            node = xmlNode;
                            break;
                        }
                }
            return node;
        }

        void CreateRoleIfNotExist() {
            using (IUnitOfWork unitOfWork = UnitOfWork.Begin()) {
                foreach (var role in _defaultRoles) {
                    var dbRole = _roleRepository.GetByName(role.Name);

                    if (dbRole == null) {
                        dbRole = _factory.CreateRole(role.Name, role.Description);

                        // 添加资源
                        var resources = role.Resources.Split(',');

                        foreach (var resourceName in resources) {
                            var defaultResource = IoC.Resolve(resourceName);
                            if (defaultResource != null) {
                                if (String.IsNullOrEmpty(defaultResource.Name)) {
                                    continue;
                                }
                                var resource = defaultResource.IsController ? _resourceRepository.FindController(defaultResource.Name) : _resourceRepository.FindAction(defaultResource.ControllName, defaultResource.Name);

                                if (resource != null) {
                                    dbRole.AddResouce(resource);
                                }
                            }

                        }

                        _roleRepository.Add(dbRole);
                    }
                }

                unitOfWork.Commit();
            }
        }

        void CreateUserIfNotrExist() {
            using (IUnitOfWork unitOfWork = UnitOfWork.Begin()) {
                foreach (var user in _defaultUsers) {
                    // account 为email
                    var dbUser = _userRepository.FindByAccountName(user.Email);

                    if (dbUser == null) {
                        dbUser = _factory.CreateUser(user.Email, user.Name, user.Password, "  ", "  ");
                        dbUser.Gender = user.Gender;

                        var role = _roleRepository.GetByName(user.Role.Name);

                        if (role != null) {
                            dbUser.AddToRole(role);
                        }

                        _userRepository.Add(dbUser);
                    }
                }

                unitOfWork.Commit();
            }
        }

        void CreateResourceIfNotrExist() {
            using (IUnitOfWork unitOfWork = UnitOfWork.Begin()) {
                foreach (var resource in _defaultResources) {
                    var dbresource = resource.IsController ? _resourceRepository.FindController(resource.Name) : _resourceRepository.FindAction(resource.ControllName, resource.Name);

                    if (dbresource == null) {
                        dbresource = _factory.CreateResource(resource.Name, resource.ControllName, resource.IsController, resource.IsAllowedNoneRoles, resource.IsAllowedAllRoles);

                        dbresource.IsHeader = resource.IsHeader;
                        dbresource.IsShow = resource.IsShow;
                        dbresource.Title = resource.Title;

                        _resourceRepository.Add(dbresource);
                    }
                }

                unitOfWork.Commit();
            }
        }
    }

代码说明

1、需要在系统启动时执行,放在Global.asax中即可

2、每次加载时只创建不存在的记录(CreateResourceIfNotrExist)

3、读取时用到了反射,用于读取控制器和方法,用返回值和类型做为过滤条件

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏潇涧技术专栏

Lint Tool Analysis (2)

本系列的几篇源码分析文档意义不大,如果你正好也在研究lint源码,或者你想知道前面自定义lint规则中提出的那几个问题,抑或你只是想大致了解下lint的源码都有...

451
来自专栏大内老A

这算是ASP.NET MVC的一个大BUG吗?

这是昨天一个同事遇到的问题,我觉得这是一个蛮大的问题,而且不像是ASP.NET MVC的设计者有意为之,换言之,这可能是ASP.NET MVC的一个Bug(不过...

1928
来自专栏跟着阿笨一起玩NET

Winfrom 如何安全简单的跨线程更新控件

来源:http://www.cnblogs.com/rainbowzc/archive/2010/09/29/1838788.html

291
来自专栏Android 研究

APK安装流程详解14——PMS中的新安装流程上(拷贝)补充

mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACK...

741
来自专栏Java成神之路

hbase_异常_01_Hbase: Failed to become active master

参考:Hbase: Failed to become active master 的解释:

653
来自专栏ASP.NET MVC5 后台权限管理系统

构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(24)-权限管理系统-将权限授权给角色

过了个年回来,回顾一下,我们上次讲了角色管理,我们这一次来讲将权限授权给角色,这一节也是大家比较关心的。因为我们已经跑通了整个系统,知道权限的流转,我们先来看一...

2517
来自专栏大内老A

.NET的资源并不限于.resx文件,你可以采用任意存储形式[上篇]

为了构建一个轻量级的资源管理框架以满足简单的本地化(Localization)的需求,我试图直接对现有的Resource编程模型进行扩展。虽然最终没能满足我们的...

2017
来自专栏ASP.NET MVC5 后台权限管理系统

ASP.NET MVC5+EF6+EasyUI 后台管理系统(87)-MVC Excel导入和导出

前言: 导入导出实在多例子,很多成熟的组建都分装了导入和导出,这一节演示利用LinqToExcel组件对Excel的导入,这个是一个极其简单的例子。 我...

4259
来自专栏Java成神之路

Java企业微信开发_08_素材管理之下载微信临时素材到本地服务器

请求地址:https://qyapi.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&med...

632
来自专栏逆向技术

64位内核第二讲,进程保护之对象钩子

         64位内核第二讲,进程保护. 一丶什么是保护. 什么是保护. 比如我们安装了xxx杀毒软件.那么此时你用任务管理器关闭.是关闭不了的.原因是内...

2586

扫描关注云+社区