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[].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[].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="" protection="All" />
</authentication>
<authorization>
<deny users="?"/>
</authorization>
- 退出时,需要注销认证用户,参考代码如下:
public ActionResult LoginOut()
{
System.Web.Security.FormsAuthentication.SignOut();
return RedirectToAction("Login", "Account");
}
- 到此,我们完成了此示例的基本功能模块,本示例源码已放置网盘,点此下载。不同用户登录系统显示的页面结果如下:


EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(九)的更多相关文章
- EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(一)
前言 本系列源自对EF6 CodeFirst的探索,但后来发现在自己项目中构建的时候遇到了一些问题以及一些解决方法,因此想作为一个系列写下来. 本系列并不是教你怎么做架构设计,但可以参照一下里面的方法 ...
- EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(六)
前言 在接下来的篇幅里将对系统的模块功能进行编写.主要以代码实现为主.这一篇我们需要完成系统模块“角色管理”的相关功能.完成后可以对系统框架结构有进一步了解. Abstract层 之前说过,Abstr ...
- EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(完)
前言 这一篇是本系列的最后一篇,虽然示例讲到这里就停止呢,但对于这些技术的学习远不能停止.虽然本示例讲的比较基础,但是正如我第一篇说到的,这个系列的目的不是说一些高端的架构设计,而是作为一个入门级,对 ...
- EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(八)
前言 本篇幅将对系统的菜单管理模块进行说明,系统的菜单采用树形结构,这样可以更好地方便层级设计和查看.本示例将说明如何通过EntityFramework读取递归的菜单树形结构,以及结合EasyUI的t ...
- EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(七)
前言 上一篇文章我们完成了系统角色管理的基本功能实现,也对系统层次结构进行了了解.这一篇我们将继续对系统的用户管理模块进行代码编写.代码没有做封装,所以大部分的逻辑代码都是相通的,只是在一些前端的细节 ...
- EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(四)
前言 这一篇,我们终于到了讲解Entity Framework CodeFirst 的时刻了,首先创建实体对象模型,然后会通过配置Fluent API的方式来对实体对象模型进行完整的数据库映射操作. ...
- EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(三)
前言 在上一篇中,我们依靠着EasyUI强大的前端布局特性把前端登录界面和主界面给搭建完成了.这一篇我们就要尝试着把整个解决方案部署到云端呢,也就是Visual Studio Online(TFVC) ...
- EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(二)
前言 写完第一篇后,我一直在想接下来应该从哪一方面开始讲.后来我觉得不用那么死板的把每一个课程和大纲都列出来吧,毕竟我又不是教书的,呵呵...我觉得就像做实验一样,我们一部分一部分的完成,最后总个结果 ...
- EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(五)
前言 在编写代码的时候,我遇到了很多关于EntityFramework6的疑问,所以现在就提前把这些问题列出来做一下解答,以便在以后的代码编写过程中减少不必要的Bug. EntityFramework ...
随机推荐
- 用STM32CubeMX创建FreeRTOS项目
1. 目标, PG13,PG14双线程双闪灯. 2. 测试平台 stm32f429i-disco keil v5.13.0.0 CubeMx 4.8.0 3. 步骤 3.1 打开cube, PG13, ...
- oracle 删除用户时的坑
ORACLE在使用 SELECT SID,SERIAL# FROM V$SESSION WHERE USERNAME='dt_zntg_trade' 删除会话时,一定要注意dt_zntg_trade的 ...
- Android动态方式破解apk终极篇(加固apk破解方式)
一.前言 今天总算迎来了破解系列的最后一篇文章了,之前的两篇文章分别为: 第一篇:如何使用Eclipse动态调试smali源码 第二篇:如何使用IDA动态调试SO文件 现在要说的就是最后一篇了,如何应 ...
- Chapter 1: 随机事件及其概率
1. 随机试验,样本点,样本空间 若试验具有下列特点: 在相同条件下可重复进行 每次试验的可能结果不止一个,且所有可能结果在实验前是已知的 实验前不能确定哪一个结果会发生 则称该试验为随机试验,常记为 ...
- Linux网络配置基础
linux网络配置常见有两种:桥接模式(Bridge)与NAT模式,还有一种Host-Only模式由于其局限性通常被舍弃就不加以说明了,下面我们介绍下桥接模式(Bridge)和NAT模式. 桥接模式( ...
- shmop ftok
http://blog.csdn.net/heiworld/article/details/25426723 对于ftok的理解 http://www.jb51.net/article/510 ...
- R中数据拆分和整合
library(data.table)ID <- c(NA,1,2,2)IDTime <- c(1,2,NA,1)TimeX1 <- c(5,3,NA,2)X1X2 <- c( ...
- Indexed 和 Stored 的区别
都是针对field的: indexed表示需不需要建立索引,以便之后对这个field进行查询: stored表示需不需要随索引同时存储这个field本身的内容,以便查询时直接从结果中获取 ...
- CentOS搭建NodeJS环境
事件驱动,承受高并发……这些耀眼的光环,使前端开发者不能不去学习NodeJS. 今天就在开发环境把NodeJS搭建起来了. 1. 下载node wget http://nodejs.org/dist/ ...
- div居中方法
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...