EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(九)

前言

  • 这一篇我们将完成系统的权限设置功能以及不同角色用户登录系统后动态加载菜单。注意:此示例权限只针对菜单级,如果园友需要更复杂的系统权限设置,可以拓展到按钮级或属性级。
  • 用户的登录采用Form认证来实现,这样可以有效地防止非授权用户或页面链接对系统造成不安全的操作。

权限设置模块

  • 页面采用角色列表和菜单列表勾选的方式,即选择角色后勾选可以操作的菜单,这样具有才角色的用户就具有操作这些菜单的权限。界面设置如下:

  

  • 界面选择的roleID和menuID我们采用字符串的方式进行拼接。在controller中采用object类型进行接收,然后进行转化后就可以得到传入的值。权限设置的参考代码如下:
   public bool SetPermit(object RoleID, object MenuIDs)
        {
            try
            {
                string[] roleArr = RoleID as string[];
                long roleID = Convert.ToInt64(roleArr[0].ToString());

                S_Role role = context.S_Roles.Where(x => x.ID.Equals(roleID)).FirstOrDefault(); //获取角色
                role.S_Menus = new List<S_Menu>();

                //删除先前设置的roleID的数据
                List<S_Menu> listdate = context.S_Roles.Where(x => x.ID.Equals(roleID)).FirstOrDefault().S_Menus.ToList();
                foreach (var item in listdate)
                {
                    role.S_Menus.Remove(item);
                }

                //写入现有的数据
                string[] MenuArr = MenuIDs as string[];
                string[] MenuArrString = MenuArr[0].ToString().TrimEnd(‘,‘).Split(‘,‘).ToArray();
                List<long> arr = new List<long>();
                foreach (var item in MenuArrString)
                {
                    arr.Add(Convert.ToInt64(item));
                }

                //必须转化为list集合,否则会出现“已有打开的与此 Command 相关联的 DataReader,必须首先将它关闭”错误
                List<S_Menu> query = (from m in context.S_Menus where arr.Contains(m.ID) select m).ToList();

                foreach (S_Menu menu in query)
                {
                    role.S_Menus.Add(menu);
                    menu.S_Roles = new List<S_Role>();
                    menu.S_Roles.Add(role);
                }

                //EF默认启用了事务提交
                context.SaveChanges();
                return true;
            }
            catch
            {
                return false;
            }
        }
  • 由于想要在权限设置成功后能够反映角色拥有操作哪些菜单的权限,因此,我们需要对角色的easyui-datagrid追加点击事件,并且异步加载具有的菜单权限。Easyui-Datagrid本身具有一个很有用的数据方法unselectAll(取消选中当前页所有的行)。但需要放置在选中的菜单权限之前。参考代码如下:
$(‘#dg‘).datagrid({
            onClickRow: function (index, data) {
                var row = $(‘#dg‘).datagrid(‘getSelected‘);
                if (row) {
                    var RoleID = row.ID;
                    $.ajax({
                        url: ‘/System/GetPermit‘,
                        type: ‘POST‘,
                        data: { RoleID: RoleID },
                        success: function (data) {
                            $(‘#dgMenu‘).treegrid(‘unselectAll‘); //重新加载

                            $(‘#dgMenu‘).treegrid({
                                onLoadSuccess: function (dataaa) {
                                    $.each(data, function (index, item) {
                                        $(‘#dgMenu‘).treegrid(‘selectRow‘, item);  //选中设置的权限
                                    });
                                }});
                        }
                    })}} });

系统登录用户获取菜单操作权限

  • 在我们把权限设置模块完成后就可以使不同角色的用户登录系统后操作不同的菜单权限。由于菜单采用的是easyui-tree来绑定的数据,所以我们需要定义一个符合easyui-tree属性的数据模型,这样就可以序列化easyui-tree识别的json数据格式呢。(这和之前的easyui-treegrid使用方式是一样的)。参考代码如下:
  public class mod_S_RoleMenuTree
    {
        public long id { get; set; }   // 节点的ID
        public string text { get; set; }  //节点显示的文字
        public string iconCls { get; set; }
        public string url { get; set; }
        public int treelevel { get; set; }
        //节点状态,有两个值  ‘open‘ or ‘closed‘, 默认为‘open‘. 当为‘closed’时说明此节点下有子节点否则此节点为叶子节点
        public string state { get; set; }
        public List<mod_S_RoleMenuTree> children { get; set; }// 子节点集合
    }
  • 在MainController中我们可以根据登录的用户名获取该用户角色所具有的菜单权限。由于此示例的菜单只设置了两级,所以没有做递归。如果需要多级菜单,可以参照上一篇文章将以下方法修改成递归方法,参考代码如下:
  public ActionResult GetRoleMenus()
        {
            string strUser = System.Web.HttpContext.Current.User.Identity.Name;
            List<S_Menu> listData = IS_Role.GetRoleMenus(strUser);

            var listDataParent = listData.Where(x => x.PID.Equals(null)).OrderBy(x => x.SerialNO);

            List<mod_S_RoleMenuTree> DataModel = new List<mod_S_RoleMenuTree>();

            foreach (var item in listDataParent)
            {
                mod_S_RoleMenuTree model = new mod_S_RoleMenuTree();
                model.id = item.ID;
                model.text = item.MenuName;
                model.iconCls = item.Icon;
                model.state = "open";
                model.url = item.Link;
                model.treelevel = item.Level;
                model.children = new List<mod_S_RoleMenuTree>();

                var children = listData.Where(x => x.PID.Equals(item.ID)).OrderBy(x => x.SerialNO);
                foreach (var childitem in children)
                {
                    mod_S_RoleMenuTree childmodel = new mod_S_RoleMenuTree();
                    childmodel.id = childitem.ID;
                    childmodel.text = childitem.MenuName;
                    childmodel.iconCls = childitem.Icon;
                    childmodel.state = "open";
                    childmodel.url = childitem.Link;
                    model.treelevel = childitem.Level;
                    model.children.Add(childmodel);
                }

                DataModel.Add(model);
            }

            return Json(DataModel, JsonRequestBehavior.AllowGet);
        }
  • 再将MainController中的Index视图中的获取菜单数据的代码替换成以下代码,这样我们可以动态从数据库中读取菜单,而不是直接读取json文件。
   <ul class="easyui-tree" id="txt"
                    data-options="url:‘/Main/GetRoleMenus‘,method:‘get‘,animate:true,lines:true"></ul>

登录功能

  • 我们为系统设置了连个账户admin\Jack,admin具有管理员角色,Jack具有操作员角色,因此两个用户登录后看到的菜单是不一样的。用户登录参考代码如下:
  [HttpPost]
  public ActionResult Login(mod_Account model)
        {
            if (null != model){
                if (IS_User.Login(model.UserName, DESEncrypt.Encrypt(model.UserPwd))){
                    System.Web.Security.FormsAuthentication.SetAuthCookie(model.UserName, false);
                    return RedirectToAction("Index", "Main");
                }
                else{
                    return View();
                }
            }
            else{
                return View();
            }
        }
  • 由于采用Form认证,所以我们还需要在配置文件中修改一下代码:
  <authentication mode="Forms">
      <forms loginUrl="/Account/Login" timeout="2880" protection="All" />
    </authentication>
    <authorization>
      <deny users="?"/>
    </authorization>
  • 退出时,需要注销认证用户,参考代码如下: 
  public ActionResult LoginOut()
        {
            System.Web.Security.FormsAuthentication.SignOut();
            return RedirectToAction("Login", "Account");
        }
  • 到此,我们完成了此示例的基本功能模块,本示例源码已放置网盘,点此下载。不同用户登录系统显示的页面结果如下:

  

  

  

时间: 2024-10-18 12:20:00

EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(九)的相关文章

EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(一)

前言 本系列源自对EF6 CodeFirst的探索,但后来发现在自己项目中构建的时候遇到了一些问题以及一些解决方法,因此想作为一个系列写下来. 本系列并不是教你怎么做架构设计,但可以参照一下里面的方法,EF系列大都采用DDD的构建方式,这也是目前最流行的.如果你想对DDD有所了解,可以在园子当中寻找那些DDD方面的文章或者是在CodePlex上下载相关的DDD设计模型源码进行研究. 如果你是一个新人或者是没有用过EF6 CodeFirst的人,那么本系列将带你一步一步构建自己的解决方案平台.如果

EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(六)

前言 在接下来的篇幅里将对系统的模块功能进行编写.主要以代码实现为主.这一篇我们需要完成系统模块“角色管理”的相关功能.完成后可以对系统框架结构有进一步了解. Abstract层 之前说过,Abstract层是对业务接口的定义,所以我们新建接口文件IS_UserRepository,定义增删改查业务的接口.这一层需要添加对Entities层的引用.代码如下: using Entities; using System.Collections.Generic; namespace Abstract

EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(四)

前言 这一篇,我们终于到了讲解Entity Framework CodeFirst 的时刻了,首先创建实体对象模型,然后会通过配置Fluent API的方式来对实体对象模型进行完整的数据库映射操作. 此篇幅中会涉及到一些Entity Frame的相关概念,会给出初步的解释.如果需要详细了解,可以查阅相关的帮助文档. EF实体对象模型的创建 EF的实体对象模型大都采用POCO类的方式创建.POCO的全称为Plain_Old_CLR_Object(简单传统CLR对象),是指那些没有从任何类继承,也没

EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(三)

前言 在上一篇中,我们依靠着EasyUI强大的前端布局特性把前端登录界面和主界面给搭建完成了.这一篇我们就要尝试着把整个解决方案部署到云端呢,也就是Visual Studio Online(TFVC)中. 在我们进行团队项目开发的过程中,或多或少的都会接触到一些源代码管理工具,比如vss.svn.tfs.git,这些工具都有着自己的特点.但最终目的都是方便团队的协作开发,提高工作效率.Visual studio从2013版本开始就为我们提供了云端管理源代码的能力.Visual Studio On

EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(完)

前言 这一篇是本系列的最后一篇,虽然示例讲到这里就停止呢,但对于这些技术的学习远不能停止.虽然本示例讲的比较基础,但是正如我第一篇说到的,这个系列的目的不是说一些高端的架构设计,而是作为一个入门级,对学习EntityFramework6构建一个简单的示例以及对其进行设计,管理,编码的过程. 应部分园友要求,博客换了一个清爽的模板.之前的模板也是为了学习一下,所以按照其他模板的样式,把自己的博客园模板修该了一下.虽然这不是写博客的主要目的,但还是从中学习到了很多,比如小插件的应用.运行js和css

EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(七)

前言 上一篇文章我们完成了系统角色管理的基本功能实现,也对系统层次结构进行了了解.这一篇我们将继续对系统的用户管理模块进行代码编写.代码没有做封装,所以大部分的逻辑代码都是相通的,只是在一些前端的细节上处理有些不同.源码将在文章的末尾给出,有兴趣的园友可以对代码做一些封装或重构,毕竟这可以减少很多的代码量. Abstract层 在这一层添加对用户管理操作的业务接口IS_UserRepository,里面定义增删改查的业务接口.代码如下: using Entities; using System.

EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(二)

前言 今天早上,看到第一篇上首页呢,多谢支持! 写完第一篇后,我一直在想接下来应该从哪一方面开始讲.后来我觉得不用那么死板的把每一个课程和大纲都列出来吧,毕竟我又不是教书的,呵呵...我觉得就像做实验一样,我们一部分一部分的完成,最后总个结果应该就出来呢.那么这一篇就来把前端的样子弄出来,至少得知道长成什么样吧.接下来就应该开始捯饬了... 下载前端框架EasyUI 到EasyUI的官网下载压缩包.一个是基于GPL的开源版,一个是商业版.我们自己做研究就下个开源版呢.目前是1.4.3的版本,解压

EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(八)

前言 本篇幅将对系统的菜单管理模块进行说明,系统的菜单采用树形结构,这样可以更好地方便层级设计和查看.本示例将说明如何通过EntityFramework读取递归的菜单树形结构,以及结合EasyUI的treegrid在Asp.net MVC上显示树形菜单和管理操作. Easyui-treegrid的使用方法 首先我们来看一下treegrid的基本使用方法.很简单,和easyui-datagrid差不多. <table title="Folder Browser" class=&qu

k8s实践(九):Helm and Kubeapps UI

环境说明: 主机名 操作系统版本 ip docker version kubelet version helm version 配置 备注 master Centos 7.6.1810 172.27.9.131 Docker 18.09.6 V1.14.2 v2.14.3 2C2G master主机 node01 Centos 7.6.1810 172.27.9.135 Docker 18.09.6 V1.14.2 v2.14.3 2C2G node节点 node02 Centos 7.6.18