前言

  • 这一篇我们将完成系统的权限设置功能以及不同角色用户登录系统后动态加载菜单。注意:此示例权限只针对菜单级,如果园友需要更复杂的系统权限设置,可以拓展到按钮级或属性级。
  • 用户的登录采用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实践(九)的更多相关文章

  1. EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(一)

    前言 本系列源自对EF6 CodeFirst的探索,但后来发现在自己项目中构建的时候遇到了一些问题以及一些解决方法,因此想作为一个系列写下来. 本系列并不是教你怎么做架构设计,但可以参照一下里面的方法 ...

  2. EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(六)

    前言 在接下来的篇幅里将对系统的模块功能进行编写.主要以代码实现为主.这一篇我们需要完成系统模块“角色管理”的相关功能.完成后可以对系统框架结构有进一步了解. Abstract层 之前说过,Abstr ...

  3. EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(完)

    前言 这一篇是本系列的最后一篇,虽然示例讲到这里就停止呢,但对于这些技术的学习远不能停止.虽然本示例讲的比较基础,但是正如我第一篇说到的,这个系列的目的不是说一些高端的架构设计,而是作为一个入门级,对 ...

  4. EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(八)

    前言 本篇幅将对系统的菜单管理模块进行说明,系统的菜单采用树形结构,这样可以更好地方便层级设计和查看.本示例将说明如何通过EntityFramework读取递归的菜单树形结构,以及结合EasyUI的t ...

  5. EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(七)

    前言 上一篇文章我们完成了系统角色管理的基本功能实现,也对系统层次结构进行了了解.这一篇我们将继续对系统的用户管理模块进行代码编写.代码没有做封装,所以大部分的逻辑代码都是相通的,只是在一些前端的细节 ...

  6. EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(四)

    前言 这一篇,我们终于到了讲解Entity Framework CodeFirst 的时刻了,首先创建实体对象模型,然后会通过配置Fluent API的方式来对实体对象模型进行完整的数据库映射操作. ...

  7. EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(三)

    前言 在上一篇中,我们依靠着EasyUI强大的前端布局特性把前端登录界面和主界面给搭建完成了.这一篇我们就要尝试着把整个解决方案部署到云端呢,也就是Visual Studio Online(TFVC) ...

  8. EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(二)

    前言 写完第一篇后,我一直在想接下来应该从哪一方面开始讲.后来我觉得不用那么死板的把每一个课程和大纲都列出来吧,毕竟我又不是教书的,呵呵...我觉得就像做实验一样,我们一部分一部分的完成,最后总个结果 ...

  9. EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(五)

    前言 在编写代码的时候,我遇到了很多关于EntityFramework6的疑问,所以现在就提前把这些问题列出来做一下解答,以便在以后的代码编写过程中减少不必要的Bug. EntityFramework ...

随机推荐

  1. animation 动画重播

    <style> div, body{ margin: 0; padding: 0; } body{ background-color: #333; } @keyframes running ...

  2. winform 移动窗体,和窗体阴影(引用)

    无边框窗体移动://窗体移动API [DllImport("user32.dll")] public static extern bool ReleaseCapture(); [D ...

  3. 简单的方式优化mysql

    参考博客 自己笔记本上向mysql导入txt数据,有一个table导入了将近4个小时,而且多个table之间都是相互之间存在关系的,所以做联合查询的时候你会发现问题会十分的多,我之前联合查询两个表就死 ...

  4. Ext5实现树形下拉框ComboBoxTree

    最近为了实现一个属性下拉框被Ext框架折腾了好几天.. 所以,首先要说的是,不管你要做什么系统.强烈建议你不要选择Ext.据我这几天的搜索,应该这个框架现在用的人也很少了. Ext框架的缺陷:框架沉重 ...

  5. Servlet开发详解

    一.Servlet简介 Servlet是sun公司提供的一门用于动态web资源的技术 sun公司在其API中提供了一个Servlet接口,用户若想开发一个动态web资源,需要完成两个步骤: 编写一个J ...

  6. angularjs指令系统系列课程(3):替换replace,内容保留transclude,作用方式restrict

    这一节我们主要看一下replace,transclude,restrict这三个参数 1.replace 可取值:bool 默认为:true 对于replace属性,设置为false表示原有指令标识不 ...

  7. Adroid 展开收起效果实现

    Layout <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns ...

  8. 尝试用md编辑器写博客, 内容为 jupyter笔记

    Matplotlib tutorial http://www.labri.fr/perso/nrougier/teaching/matplotlib/#introduction %matplotlib ...

  9. JOIN关联表中ON,WHERE后面跟条件的区别

    select * from td  left join (select case_id as sup_case_id , count(*) supervise_number from  td_kcdc ...

  10. RANSAC 剔除错误匹配 估计模型

    随机抽样一致,这个算法,我以前一直都没有理解透彻.只知道可以用来直线拟合,网上大多数中文博客也都是写直线拟合的,但是用来匹配二维特征的时候,总还是没弄明白. 基本概念参考 http://www.cnb ...