侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

MVC网站开发之权限管理篇

php  /  管理员 发布于 8年前   146

一、前言

刚到公司没多长时间就开始接触MVC到现在不能说懂了,只能说到达会用这个层次吧,感觉MVC用来写Web还是很强大的,层次清晰。

今天我来写写关于权限管理这一块,自我感觉网站的权限主要分为菜单权限和角色权限,首先说角色权限,比较简单不同角色可以看到不同页面这就是角色权限,菜单权限也可以说是操作权限,就是具体到某一个按钮,或某一个下拉框的查看权限或使用权限。

二、角色权限

1.用户角色

首先来角色权限,每个用户有着多样不同的角色,一对多的关系。

2.菜单管理

在菜单管理中我们就可以这样管理,某一菜单,那一角色可以看到就打上√这样比较容易控制。

3.数据库

再来看数据库中,要有角色的表以及用户与角色关系表。

再就是角色与菜单的关系表,其中PermissionIDs字段为操作权限以|隔开。

4.用户登录

当用户登录时我们就可以根据登陆人的ID取到他的所有角色存到Session中,并根据登录人查出相应的菜单。 

//角色基本信息   SqlHelperParameter sqlHelperParameterRole = new SqlHelperParameter();   sqlHelperParameterRole.Add("UserId", dtUserRow["UserId"].ToString());   DataTable dtRole = SqlHelper.ExecuteDataTable(@"   select    Sys_Roles.RoleId,   Sys_Roles.RoleName,   Sys_Roles.Weight    from (    select UserId,RoleId from Sys_UsersInRoles     where UserId =@UserId   ) as a left join Sys_Roles on a.RoleId = Sys_Roles.RoleId", sqlHelperParameterRole);   int dtRoleCount = dtRole.Rows.Count;   RoleWeightMax = int.MaxValue;   for (int i = 0; i < dtRoleCount; i++)   {    RolesSession rs = new RolesSession();    rs.RoleID = Guid.Parse(dtRole.Rows[i]["RoleId"].ToString());    rs.RoleName = dtRole.Rows[i]["RoleName"].ToString();    rs.Weight = Convert.ToInt32(dtRole.Rows[i]["Weight"]);    if (RoleWeightMax > rs.Weight)    {     RoleWeightMax = rs.Weight;    }    RoleList.Add(rs);   }

public class RolesSession {  public Guid RoleID { get; set; }  public string RoleName { get; set; }  //权重  public int Weight { get; set; } }

前台代码:

 <div data-options="region:'west',split:true" title="导航菜单" style="width: 200px; padding1: 1px; overflow: hidden;" id="left_nav"> <div class="easyui-accordion" data-options="fit:true,border:false">  @H9C.PMS.BLL.LogOn.MenuList.GetMenu(ViewBag.UserName) </div></div>

控制器: 

public static MvcHtmlString GetMenu(string userName)  {   Menu menu = new Menu();   MenuStructure ms = menu.GetMenuListStructure(userName);   if (ms != null)   {    ms.Children.Remove(ms.Children.FirstOrDefault(o => o.ModelCode == "0" && o.ParentID == "0"));   }   return new MvcHtmlString(MenuNav("0", ms));  }  private static string MenuNav(string menuCode, MenuStructure menuStruc)  {   if (menuStruc == null)   {    return "<div>没有可用菜单</div>";   }   List<MenuStructure> list = menuStruc.Children.Where(m => m.ParentID == menuCode).ToList();   StringBuilder sbMenu = new StringBuilder();   foreach (var item in list)   {    if (item.ParentID == "0")    {     sbMenu.Append("<div title=\"" + item.Title + "\" style=\"overflow: auto;\">");     sbMenu.Append("<ul id=\"menu" + item.ParentID + "\" class=\"easyui-tree\" animate=\"true\" dnd=\"true\">");     sbMenu.Append("<li>");    }    else    {     sbMenu.Append("<ul id=\"menu" + item.ParentID + "\" class=\"easyui-tree\" animate=\"true\" dnd=\"true\">");     if (item.Children.Count == 0)     {      sbMenu.Append("<li>");     }     else     {      sbMenu.Append("<li state=\"closed\">");     }    }    sbMenu.Append("<span>");    if (item.Url == "/")    {     sbMenu.Append("<a class=\"e-submenu\" href=\"javascript:void(0);\" title=\"" + item.Title + "\" >");    }    else    {     string tabsIcon = "14";     if (!string.IsNullOrWhiteSpace(item.Icon))     {      tabsIcon = item.Icon.Replace("/Content/images/", "").Replace(".png", "");     }     sbMenu.Append("<a class=\"e-submenu\" href=\"#\" onclick=\"addTab('" + item.Url + "','" + item.Title + "')\" >");     sbMenu.Append("<img src=\"" + item.Icon + "\" >");    }    sbMenu.Append("" + item.Title + "");    sbMenu.Append("</a></span>");    if (IsExistParent(item.ModelCode, item))    {     sbMenu.Append(MenuNav(item.ModelCode, item));    }    sbMenu.Append("</li>");    sbMenu.Append("</ul>");    if (item.ParentID == "0")    {     sbMenu.Append("</div>");    }   }   return sbMenu.ToString();  }  private static bool IsExistParent(string modelCode, MenuStructure menuModels)  {   var query = menuModels.Children.FirstOrDefault(m => m.ParentID == modelCode);   if (query == null)   {    return false;   }   return true;  }

菜单类: 

public class MenuStructure {  public string ModelCode;  public string Title;  public string Icon;  public string Url;  public string ParentID;  public List<MenuStructure> Children = new List<MenuStructure>(); }

其中GetMenuListStructure()方法就是根据用户名获取菜单列表结构,我这里用户名在数据库中是唯一的,在这里注意一点比较麻烦的是根据类可以看出菜单是有父菜单子菜单的所以方法中需要有两个循环去添加。 

三、菜单权限
也就是操作权限,比如某一按钮的操作权限。首先我们把所有关于按钮的操作权限存放到一个类中,(有更好的方法请向我推荐谢谢)

public class Menus {  public static int gongdan = 503000000;//任务工单 } 

然后我们需要操作权限的按钮所在的页面的Controllers(加载页面)中存到ViewBag里,如下: 

public ActionResult Index()  {H9C.PMS.BLL.RBAC.Permission pm = new BLL.RBAC.Permission();ViewBag.IsReportPlan = pm.IsRoleHavePermissions(Roles.Shigongduizhang, Menus.gongdan, base.UserSessionModel, Menus.GongdanReportPlanByShiGongTeamer); //上报施工计划   return View();  }

/// <summary>  /// 判断某权限是否在获取某角色权限的列表中  /// </summary>  /// <param name="roleId"></param>  /// <param name="modelCode"></param>  /// <param name="userSessionModel"></param>  /// <param name="permissionCode"></param>  /// <returns></returns>  public bool IsRoleHavePermissions(Guid roleId, int modelCode, UserSessionModel userSessionModel, int permissionCode)  {   List<PermissionModel> permissionModelList = this.GetRolePermissionList(roleId, modelCode, userSessionModel);   if (permissionModelList == null)   {    return false;   }   foreach (var o in permissionModelList)   {    if (o.PCode == permissionCode)    {     return true;    }   }   return false;  }

/// <summary>  /// 获取某角色权限的列表  /// </summary>  /// <param name="roleId"></param>  /// <param name="modelCode"></param>  /// <param name="userSessionModel"></param>  /// <returns></returns>  public List<PermissionModel> GetRolePermissionList(Guid roleId, int modelCode, UserSessionModel userSessionModel)  {   foreach (var o in userSessionModel.RoleList)   {    if (o.RoleID == roleId)    {     List<Model.RBAC.PermissionModel> permissionList = this.PermissionList(roleId, modelCode);     return permissionList;    }   }   return null;  }

/// <summary>  /// 获取某菜单某角色下具有的权限  /// </summary>  /// <param name="modelId"></param>  /// <param name="menuId"></param>  /// <returns></returns>  public List<PermissionModel> PermissionList(Guid roleId, int menuId)  {   List<PermissionModel> pmList = new List<PermissionModel>();   using (RBACContext connEF = new RBACContext())   {    Sys_Role_Model_Permissions srmp = connEF.Sys_Role_Model_Permissions.FirstOrDefault(o => o.ModelID == menuId && o.RoleId == roleId);    if (srmp != null)    {     string permissions = srmp.PermissionIDs;     if (!string.IsNullOrWhiteSpace(permissions))     {      string[] pids = permissions.Split(new char[] { '|' });      for (int i = 0; i < pids.Length; i++)      {       if (!string.IsNullOrWhiteSpace(pids[i]))       {        pmList.Add(new PermissionModel() {         ModelCode = menuId,         PCode = Convert.ToInt32(pids[i]),         PName =""        });       }      }     }    }   }   return pmList;  }

最后一个方法中运用到了EF根据菜单以及角色获取某菜单某角色下具有的权限
前台就非常简单的: 

@if (ViewBag.IsReportPlan == true)  {   @:      <a href="" class="easyui-linkbutton l-btn"     iconcls="icon-add">按钮</a>   } 

四、尾声 

总结一下,就是首先要有一个菜单管理的模块,它不但可以管理菜单还可以管理菜单中的权限以及每个角色关于菜单的权限,然后就是后台的控制,上面权限Model中存的权重,指的是每一角色都有权重,每一个用户都有他的最大权重,根据这个权重我们就可以做很多条件的控制,简单的说也是为了方便吧。
第一篇技术文档,文笔还需要多锻炼,以后会试着多写博文,不会写文档的码农不是好程序员。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


  • 上一条:
    一个支持普通分页和综合分页的MVC分页Helper
    下一条:
    学习制作MVC4分页控件(下)
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • 用Time Warden监控PHP中的代码处理时间(0个评论)
    • 在PHP中使用array_pop + yield实现读取超大型目录功能示例(0个评论)
    • Property Hooks RFC在PHP 8.4中越来越接近现实(0个评论)
    • 近期文章
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-06
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-11
    • 2017-12
    • 2018-01
    • 2018-02
    • 2018-03
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-09
    • 2021-02
    • 2021-03
    • 2021-04
    • 2021-05
    • 2021-06
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2021-12
    • 2022-01
    • 2022-02
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-08
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    • 2024-05
    • 2024-06
    • 2024-07
    • 2024-09
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客