一、前言

刚到公司没多长时间就开始接触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 = ; 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 == "" && o.ParentID == ""));
}
return new MvcHtmlString(MenuNav("", 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 == "")
{
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 == )
{
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 = "";
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 == "")
{
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 = ;//任务工单
}

然后我们需要操作权限的按钮所在的页面的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 = ; 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)
{
@:&nbsp;&nbsp;
<a href="#" class="easyui-linkbutton l-btn"
iconcls="icon-add">按钮</a>
}

四、尾声

总结一下,就是首先要有一个菜单管理的模块,它不但可以管理菜单还可以管理菜单中的权限以及每个角色关于菜单的权限,然后就是后台的控制,上面权限Model中存的权重,指的是每一角色都有权重,每一个用户都有他的最大权重,根据这个权重我们就可以做很多条件的控制,简单的说也是为了方便吧。

第一篇技术文档,文笔还需要多锻炼,以后会试着多写博文,不会写文档的码农不是好程序员。

MVC之权限管理-网站开发之路的更多相关文章

  1. python开发之路:python数据类型(老王版)

    python开发之路:python数据类型 你辞职当了某类似微博的社交网站的底层python开发主管,官还算高. 一次老板让你编写一个登陆的程序.咔嚓,编出来了.执行一看,我的妈,报错? 这次你又让媳 ...

  2. MVC中权限管理

    权限管理,一般指根据系统设置的安全规则或者安全策略,用户可以访问而且只能访问自己被授权的资源,不多不少.权限管理几乎出现在任何系统里面,只要有用户和密码的系统.权限管理还是比较复杂的,有的固定到某个模 ...

  3. python全栈开发之路

    一.Python基础 python简介 python数据类型(数字\字符串\列表) python数据类型(元组\字典) python数据类型(集合) python占位符%s,%d,%r,%f prin ...

  4. asp.net mvc的权限管理设计

    现在集中展示用户-角色-权限管理的功能,因此,所有数据表一律简化处理.   1 后台管理效果 (1)角色管理 (2)权限管理   2 数据库设计(MSSQL) (1)用户表dbo.Users 项 类型 ...

  5. 朴素的标题:MVC中权限管理实践

    基于MVC的web项目最好的权限控制方式我认为是对Action的控制,实现思路记录于此,权限管理分成两个部分授权.认证. 一.授权 1.读取当前项目中的所有需要控制的Action /// <su ...

  6. Python开发之路:目录篇

    第一部分:Python基础知识 本篇主要python基础知识的积累和学习,其中包括python的介绍.基本数据类型.函数.模块及面向对象等.  第一篇:Python简介  第二篇:Python基本知识 ...

  7. Sea.js创始人玉伯的前端开发之路

    在Web应用程序的用户体验越来越被重视的今天,前端开发的地位也上升到了前所未有的高度,而随之而来的也有更多的挑战. 为了将前端开发者繁重的工作变得简单,框架应运而生.国内也不乏一些非常优秀的前端开发框 ...

  8. 【开源专访】Sea.js创始人玉伯的前端开发之路

    摘要:玉伯,淘宝前端类库 KISSY.前端模块化开发框架SeaJS.前端基础类库Arale的创始人.本期[开源专访]我们邀请玉伯来为我们分享一些关于前端框架.前端开发的那些事,以及前端大牛是如何炼成的 ...

  9. android开发之路01

    一.android系统被分为4个层次:1.最下层的是linux核心,包括多个驱动程序,提供了操作系统应该具备的核心功能:2.在linux核心之上,包括两个部分,一部分是Android Runtime( ...

随机推荐

  1. Microchip微芯HCS301解密HCS360解密HCS361芯片解密多少钱?

    Microchip微芯HCS系列芯片解密型号: HCS101 | HCS200 | HCS201 | HCS201T | HCS300 | HCS300T HCS301 | HCS301T | HCS ...

  2. StringEscapeUtils类的转义与反转义方法

    第一步.下载Jar包(commons-lang.jar) 下载地址:http://commons.apache.org/proper/commons-lang/download_lang.cgi 第二 ...

  3. 如何让win10实现关机确认-暂没确认

    为了实现关机时有提示确认,防止不小心触碰后不提示就关机了.本人安装有360软件小助手,发生过此事多次. 1.网上找到 http://zhidao.baidu.com/link?url=dYB0fl2S ...

  4. RUDP之一 —— UDP VS TCP

    原文链接 原文:http://gafferongames.com/networking-for-game-programmers/udp-vs-tcp/ 介绍 大家好,我是Glenn Fiedler, ...

  5. PHP伪静态

    伪静态 从形式上看是一个静态地址,实际上还是访问的动态地址, 比如:访问:http://www.abc.com/news-sport-id123.html 实际上是:http://www.abc.co ...

  6. Hibernate加载数据失败failed to lazily initialize a collection of role

    在测试获取数据库中的数据或者在页面获取时,有时会遇到这样的错误提示: failed to lazily initialize a collection of role: com.exam.entity ...

  7. vim操作

    2.vi的基本操作 a) 进入vi    在系统提示符号输入vi及文件名称后,就进入vi全屏幕编辑画面: $ vi myfile 不过有一点要特别注意,就是您进入vi之后,是处于「命令行模式(comm ...

  8. jQuery命名空间,插件开发

    jQuery插件的开发包括两种: 一种是类级别的插件开发,即给jQuery添加新的全局函数,相当于给jQuery类本身添加方法.jQuery的全局函数就是属于jQuery命名空间的函数,另一种是对象级 ...

  9. 神奇的 CURL 命令

    CURL? 嗯,说来话长了~~~~ 这东西现在已经是苹果机上内置的命令行工具之一了,可见其魅力之一斑 1) 二话不说,先从这里开始吧! curl http: //www.yahoo.com   回车之 ...

  10. RSA+DES动态加密

    RSA可以用于加密,其加密强度很高,被人攻克的可能性极小.但是其加密速度很慢,如果对一段长数据进行加密是不现实的.因为无论加密还是解密都需要很长时间.所以通常是先用对称加密算法(DES, AES等)对 ...