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 ...
随机推荐
- C扩展python的module和Type
有许多理由给CPython写扩展,比如 1.性能低 2.重复用别人的C/C++代码 3.在自己的程序中定制python 4.为了方便 等等. 写这种扩展其实都是套路,不过最好要有对CPython源码有 ...
- discuz教程:discuz模板js与jQuery冲突的解决方案
今天在做discuz模板的时候,用到jquery的时候和原来主题js冲突.这个主要是Discuz X使用了$(id)作为dom节点的获取方法,而$符号刚好与jQuery的默认符号相冲突. 以下是基于之 ...
- HQL查询——from子句
HQL查询--from子句 1.from是最基本的HQL语句,from关键字后紧跟持久化类的类名: from Person 表示从Person持久化类中选出全部的实例. 2.推荐为持久化类的每个实例起 ...
- 用Python生成组织机构代码,附源码
#!/usr/bin/python import random def haoma(): ww = [3,7,9,10,5,8,4,2]#suan fa yin zi cc = [] dd=0 for ...
- Javascript学习笔记:闭包题解(1)
代码: function createFunctions(){ var result=[]; for(var i=0;i<10;i++){ result[i]=function(){ retur ...
- stst
静态代码块如果不要static 那么只要生成新的该对象,则会执行{}内的代码 super.onDestroy() 先后顺序问题 Ctrl + Alt + F refromat code目前看来不能对代 ...
- rgba()兼容IE8
CSS: //一般的高级浏览器都支持 background: rgba(255,255,255,0.1); //IE8下 filter:progid:DXImageTransform.Microsof ...
- 个人博客作业week7
个人阅读作业week7 一.瀑布 软件工程的瀑布模型是1970年由Winston Royce提出来的,即软件的开发按照一个严格的.顺序的.单次的瀑布流开发周期.例如需求分析阶段.概要设计阶段.详细设计 ...
- Lambda表达式入门
Lambda表达式是Java 8的重要更新,也是一个被广大开发者期待已久的新特性,Lambda表达式支持将代码块作为方法参数,Lambda表达式允许使用更简洁的代码来创建只有一个抽象方法的接口(这种接 ...
- layer弹出层全屏及关闭
一.首先引用JS文件 <script src="../../js/common/layer/layer.js"></script> 二.全屏调用以下代码 v ...