【C#MVC4】菜单管理和访问权限分配(三)

若坚持反复研究之前的步骤,到了这里,相信你不再对C#MVC懵懵懂懂了。进行到这里也渐渐接触到核心了。不得不停下业务,单开一篇讲述一下我们这个Demo是如何加载菜单,显示到easyui的tree上面的。实现方式有很多种,但是原理基本一致,

获取数据源,绑定数据源,显示(看着很废话,好像什么也没告诉你,其实已经将最本质的告诉了你…)实际上很多控件和技术就是基于这个实现的。大部分东西,只要你到他的数据源在哪,绑定方式是什么,基本没什么东西是难理解的,无非是应用了新的框架或是技术,这个东西网上检索很容易得到解决方案。所以当你遇到一个问题的时候问问自己,数据源在哪。很多问题迎刃而解。(小小程序员的乱语,大牛请自动过滤)。

闲言不语,我们是通过xml文件获取菜单信息,然后读取xml信息,将其拼接成html,然后在easyui的tree控件上,可以直接显示。以我浅薄的知识来看,是比较简单的一种实现方式,并且减轻了服务器上数据库的一些压力,因为大部分用户的菜单很少变更,所以这种实现方式,虽然实现起来颇为麻烦,但是还是有一定优势的。当然最终的数据源是数据库的表了,这里的xml你可以理解为一种缓存机制。
因为我刚刚建的数据库,里面并没有信息,所以我这里自己建立一个xml文件,手动模拟几个菜单,等全部项目写完之后,我会回头将这一块获取菜单的代码重写,那时候你应该会有一种,哦,原来如此 的感觉。

XML文件:

这里写图片描述

代码:

<UserMenu>
  <HderMenu MenuName="Setting" MenuUrl="" MenuIcon="icon-system">
    <SubMenu MenuName="Menu Management" MenuUrl="/Admin/MenuList" MenuIcon="icon-system" />
    <SubMenu MenuName="Access Management" MenuUrl="/Admin/AssignPermission" MenuIcon="icon-system" />
    <SubMenu MenuName="Test" MenuUrl="/Test/Test" MenuIcon="icon-system" />
  </HderMenu>
</UserMenu>

我来稍作分析:
:主节点,标识文档的作用。
:父节点(其实不应该这么叫,但是相对于菜单结构,它是父节点,为了避免你们混乱),放置一级菜单节点,一级菜单,没有太多意义,只是对下面的菜单的一个分类。
:子节点,放置二级菜单节点,这个才是真正具有跳转链接的菜单项。用户根据其具有的url属性,点击后跳转到相应的action,返回至相应的视图。

属性:MenuName,菜单名;MenuUrl,链接;MenuIcon,图标信息;

我们了解了程序是根据xml加载数据的,那么如何绑定呢?

这里在common中,抽取了一个解析xml的方法,将xml的信息最终拼接成一段html片段,返回给视图,然后视图进行展示。

 public static string LoadMenuXML(string xmlpath)
        {
            string usermenu = "";
            XmlDocument doc = new XmlDocument();
            if (!System.IO.File.Exists(xmlpath))
            {
                return "";
            }
            doc.Load(xmlpath);
            XmlElement root = doc.DocumentElement;

            for (int i = 0; i < root.ChildNodes.Count; i++)
            {
                XmlNode Hnodel = root.ChildNodes.Item(i);

                usermenu += string.Format("<li data-options=\"iconCls:'icon-system',state:'closed'\"><span>{0}</span><ul>", Hnodel.Attributes["MenuName"].Value);
                for (int j = 0; j < Hnodel.ChildNodes.Count; j++)
                {
                    XmlNode Cnodel = Hnodel.ChildNodes.Item(j);
                    usermenu += string.Format("<li data-options=\"iconCls:'{0}'\"><a style=\"text-decoration:none;color:black;\" href=\"javascript:addTab('{1}','{2}')\">{3}</a></li>", Cnodel.Attributes["MenuIcon"].Value, Cnodel.Attributes["MenuName"].Value, Cnodel.Attributes["MenuUrl"].Value, Cnodel.Attributes["MenuName"].Value);
                }
                usermenu += string.Format("</ul></li>");
            }
            return usermenu;
        }

对于没有接触过xml的朋友,这里可以称为一个技术难点吧,我如果说让你们自己网上检索,会不会被喷?,这里我稍作解释:

XmlDocument doc = new XmlDocument();

建立一个xml对象,引入System.XML的dll即可使用。

doc.Load(xmlpath);

根据路径加载xml到对象中,这个路径是一个完整的路径哦,包含文件物理路径和文件名,文件后缀。这里大牛应该看出来了,对这个文件是放在服务器上。这样会对服务器造成一定的压力(当用户过多时),但是相比较那些对数据库使用频繁的系统,可以牺牲内存换取运行速度。

XmlElement root = doc.DocumentElement;

获取根节点,也就是我们上面的节点。然后便利根节点下面的父节点(对于xml文件应该称为子节点)

XmlNode Hnodel = root.ChildNodes.Item(i);

usermenu += string.Format(“

  • {0}
    • ”, Hnodel.Attributes[“MenuName”].Value);
  • 获取当前遍历中的菜单父节点,并且遍历该菜单父节点,查询其所属的菜单子节点。
    并将父节点中的菜单信息,拼接进ul元素中。
    这里用了C#中字符串的Format方法,看一下官方api如何解释:
    将指定字符串中的一个或多个格式对象替换为指定对象的字符串表示形式。

    Hnodel.Attributes[“MenuName”].Value,将节点中属性为MenuName的值取出来赋给{0},

    XmlNode Cnodel = Hnodel.ChildNodes.Item(j);
    usermenu += string.Format(“

  • {3}
  • “, Cnodel.Attributes[“MenuIcon”].Value, Cnodel.Attributes[“MenuName”].Value, Cnodel.Attributes[“MenuUrl”].Value, Cnodel.Attributes[“MenuName”].Value);

    获取当前遍历的菜单子节点。并将子节点中的菜单信息拼接进li元素中。

    最后我们就得到了一个包含所有菜单信息的html的片段,将这个片段直接返回给视图,easyui就可以正常加载了。
    看一下controller中的写法:

     public ActionResult Home()
            {
                User_Master userMaster = (User_Master)Session["UserMaster"];
                ViewBag.User = userMaster.User_Name;
                ViewBag.Date = DateTime.Now;
    
                string userMasterId = userMaster.User_Master_Id.ToString();
                string userMenuPath = System.Configuration.ConfigurationManager.AppSettings["UserMenuPath"].ToString().Trim();
                string xmlPath = userMenuPath + userMasterId + ".xml";
                ViewBag.MenuTreeList = MenuXMLHelper.LoadMenuXML(xmlPath);
                return View();
            }

    那么这个userMenuPath 在哪里设置的呢?是在web下面的config文件中设置:

    这里写图片描述

    这样,我们还需在自己本地建立相应为问价夹,将刚刚的xml文件放进去,注意xml的命名哦,是以User_Maser_Id做的名字,这样可以唯一标示该用户的登录菜单。

    还要讲我们之前在页面注释的tree放开哦:

    这里写图片描述

    最终显示:

    这里写图片描述

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
MVC WebApi 用户权限验证及授权DEMO 前言:Web 用户的身份验证,及页面操作权限验证是B/S系统的基础功能,一个功能复杂的业务应用系统,通过角色授权来控制用户访问,本文通过Form认证,Mvc的Controller基类及Action的权限验证来实现Web系统登录,Mvc前端权限校验以及WebApi服务端的访问校验功能。 1 Web Form认证介绍 Web应用的访问方式因为是基于浏览器的Http地址请求,所以需要验证用户身份的合法性。目前常见的方式是Form认证,其处理逻辑描述如下: 1) 用户首先要在登录页面输入用户名和密码,然后登录系统,获取合法身份的票据,再执行后续业务处理操作; 2) 用户在没有登录的情况下提交Http页面访问请求,如果该页面不允许匿名访问,则直接跳转到登录页面; 3) 对于允许匿名访问的页面请求,系统不做权限验证,直接处理业务数据,并返回给前端; 4) 对于不同权限要求的页面Action操作,系统需要校验用户角色,计算权限列表,如果请求操作在权限列表中,则正常访问,如果不在权限列表中,则提示“未授权的访问操作”到异常处理页面。 2 WebApi 服务端Basic 方式验证 WebApi服务端接收访问请求,需要做安全验证处理,验证处理步骤如下: 1) 如果是合法的Http请求,在Http请求头中会有用户身份的票据信息,服务端会读取票据信息,并校验票据信息是否完整有效,如果满足校验要求,则进行业务数据的处理,并返回给请求发起方; 2) 如果没有票据信息,或者票据信息不是合法的,则返回“未授权的访问”异常消息给前端,由前端处理此异常。 3 登录及权限验证流程 1) 用户打开浏览器,并在地址栏中输入页面请求地址,提交; 2) 浏览器解析Http请求,发送到Web服务器;Web服务器验证用户请求,首先判断是否有登录的票据信息; 3) 用户没有登录票据信息,则跳转到登录页面; 4) 用户输入用户名和密码信息; 5) 浏览器提交登录表单数据给Web服务器; 6) Web服务需要验证用户名和密码是否匹配,发送api请求给api服务器; 7) api用户账户服务根据用户名,读取存储在数据库中的用户资料,判断密码是否匹配; 7.1)如果用户名和密码不匹配,则提示密码错误等信息,然该用户重新填写登录资料; 7.2)如果验证通过,则保存用户票据信息; 8) 接第3步,如果用户有登录票据信息,则跳转到用户请求的页面; 9) 验证用户对当前要操作的页面或页面元素是否有权限操作,首先需要发起api服务请求,获取用户的权限数据; 10). api用户权限服务根据用户名,查找该用户的角色信息,并计算用户权限列表,封装为Json数据并返回; 11). 当用户有权限操作页面或页面元素时,跳转到页面,并由页面Controller提交业务数据处理请求到api服务器; 如果用户没有权限访问该页面或页面元素时,则显示“未授权的访问操作”,跳转到系统异常处理页面。 12). api业务服务处理业务逻辑,并将结果以Json 数据返回; 13). 返回渲染后的页面给浏览器前端,并呈现业务数据到页面; 14). 用户填写业务数据,或者查找业务数据; 15). 当填写或查找完业务数据后,用户提交表单数据; 16). 浏览器脚本提交get,post等请求给web服务器,由web服务器再次解析请求操作,重复步骤2的后续流程; 17). 当api服务器验证用户身份是,没有可信用户票据,系统提示“未授权的访问操作”,跳转到系统异常处理页面。
好的,以下是一个简单的 C# Dev 实现示例,仅供参考: 首先,我们需要定义一个菜单项类,用于存储菜单项的名称、命令和权限等信息: ```csharp public class MenuItem { public string Name { get; set; } // 菜单项名称 public string Command { get; set; } // 菜单项命令 public string Permission { get; set; } // 菜单项权限 } ``` 然后,我们需要定义一个菜单管理器类,用于管理菜单项的创建、删除、修改和权限控制等操作: ```csharp public class MenuManager { private List<MenuItem> _menuItems; // 菜单项列表 public MenuManager() { _menuItems = new List<MenuItem>(); } // 添加菜单项 public void AddMenuItem(MenuItem menuItem) { _menuItems.Add(menuItem); } // 删除菜单项 public void RemoveMenuItem(MenuItem menuItem) { _menuItems.Remove(menuItem); } // 修改菜单项 public void ModifyMenuItem(MenuItem menuItem) { // 根据菜单项名称查找对应的菜单项 var item = _menuItems.FirstOrDefault(x => x.Name == menuItem.Name); if (item != null) { // 更新菜单项信息 item.Command = menuItem.Command; item.Permission = menuItem.Permission; } } // 检查菜单项权限 public bool CheckPermission(string menuItemName, string userPermission) { // 根据菜单项名称查找对应的菜单项 var item = _menuItems.FirstOrDefault(x => x.Name == menuItemName); if (item != null) { // 检查用户权限是否包含菜单项权限 return userPermission.Contains(item.Permission); } return false; } } ``` 最后,我们可以在应用程序中创建一个菜单控件,并将菜单管理器对象与菜单控件关联。当用户点击菜单项时,我们可以调用菜单管理器的 `CheckPermission` 方法来检查用户权限是否允许执行对应的命令。 下面是一个简单的示例代码: ```csharp public partial class MainForm : Form { private MenuManager _menuManager; public MainForm() { InitializeComponent(); // 创建菜单管理器 _menuManager = new MenuManager(); // 添加菜单项 _menuManager.AddMenuItem(new MenuItem { Name = "文件", Command = "File", Permission = "Admin" }); _menuManager.AddMenuItem(new MenuItem { Name = "编辑", Command = "Edit", Permission = "User" }); // 创建菜单 var menuStrip = new MenuStrip(); var fileMenu = new ToolStripMenuItem("文件"); var editMenu = new ToolStripMenuItem("编辑"); menuStrip.Items.Add(fileMenu); menuStrip.Items.Add(editMenu); // 添加菜单项 foreach (var item in _menuManager.GetMenuItems()) { var menuItem = new ToolStripMenuItem(item.Name); menuItem.Tag = item.Command; if (_menuManager.CheckPermission(item.Name, "Admin")) { fileMenu.DropDownItems.Add(menuItem); } if (_menuManager.CheckPermission(item.Name, "User")) { editMenu.DropDownItems.Add(menuItem); } } // 将菜单添加到窗体 this.Controls.Add(menuStrip); } // 菜单项点击事件 private void MenuItem_Click(object sender, EventArgs e) { var menuItem = sender as ToolStripMenuItem; var command = menuItem.Tag.ToString(); // 执行对应的命令 // ... } } ``` 在这个示例中,我们创建了一个 `MainForm` 窗体,在窗体的构造函数中创建了菜单管理器和菜单控件,并将菜单管理器的菜单项添加到菜单控件中。在菜单项点击事件中,我们可以根据菜单项的 `Tag` 属性获取对应的命令,并执行相应的操作。在添加菜单项时,我们使用 `CheckPermission` 方法来检查用户权限是否允许添加菜单项。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值