ASP.NET权限管理(一)

在asp.net后台管理系统开发中,有一个永远绕不过去的核心功能,那就是权限管理。他使你的整个管理系统活了过来,可以适应公司不同职位人员的使用。
下边是我搭得简易界面效果图:
这里写图片描述

1、基本需求

看界面你就知道,你首先最少应该有三个模块显示,包括你的模块管理、角色管理、管理员的人员管理。

在数据库中你最少需要四个表,其他的看个人需要了。这四个表分别是
Module(模块表)、User(管理员表)、Role(角色表)、Role_Module(角色_模块授权记录表)。

2、界面生成

因为我使用的是EF,所以实体类生成就直接跳过了。

页面搭建和基本的页面显示使用的是Ajax+easyUI,这个也随自己的写法写,毕竟每个人的设计都不一样。

3、登录界面

做权限你肯定需要一个登录页面,登录页面找模板还是自己设计需要你自己找了,我主要是说一下后台的代码,进行功能的实现。

首先在登录的数据访问层(LoginDal)中添加对数据的操作

 public IEnumerable<Module> GetMenu(int rid)
 {
return Ef.Role_Module.Where(x => x.Role.ID == rid 

&&x.Module.M_type=="1" && 

x.Module.M_ParentID==0).ToList().Select(x => new Module { 

M_name = x.Module.M_name,M_path = x.Module.M_path, 

M_IconCls = x.Module.M_IconCls,ID=x.Module.ID }).ToList();
        }

注:(1)IEnumerable<>是一个数据的结构,指可用foreach遍历的“集合”。

http://bbs.csdn.net/topics/391905003?page=1
他会对你理解IEnumerable<>有一些帮助

(2)方法是通过不同角色、是否是为“1”一级菜单,是否是为0的菜单,不是按钮。来查出一级菜单,然后查询一个NEW Module数据。


然后是在业务逻辑层(LoginBll)中进行业务操作:

 public IEnumerable<Module> GetMenu(int rid)
 {
     LoginDal realDal = (LoginDal)Dal;
     return realDal.GetMenu(rid);
 }

继承Dal中的方法。

 public User GetUserByNamePaw(LoginModel model)
{
Expression<Func<User, bool>> where = x => x.U_name == model.name && x.U_pwd == model.pwd;
return Dal.Search(where).FirstOrDefault();
}

LoginModel是我自定义的一个实体类,其中存放了定义的密码,账号和可能用到的验证码。

Expression<Func<User, bool>根据条件动态生成LINQ查询条件,将Func类型的变量作为参数传给Where方法。
在EF中,如果单一将Func类型的变量作为参数传给Where方法进行LINQ查询,会造成全表查询的错误,将整个数据库表中的数据加载到内存

 [Required]
public string name { get; set; }
 [Required]
public string pwd { get; set; }
 [Required]
public string code { get; set; }

方法使model类中的元素和数据库中的元素对应。然后返回Dal中的查询方法。

最后在Login的控制器中实现对账号密码的操作。

public ActionResult Login(string name, string pwd)
{
 var loginUser = Bll.Search(x => x.U_name == name && x.U_pwd == pwd).FirstOrDefault();
 if (loginUser != null)
   {
     Session["LoginUser"] = loginUser;
     string mag = "登录成功";
     var user = Session["LoginUser"];
     return Json(new { state = true, mag =  mag},JsonRequestBehavior.AllowGet);
   }
   else
   {
     string  mag = "登录失败";
     return Json(new { state = false, mag = mag }, JsonRequestBehavior.AllowGet);
    }
  }

获取密码,判断密码是不是非空,只有一个判断,比较简单。

在前台加入常用的JavaScript前台验证

 function submit1() {
  if ($("#Username").val() == "" || $("#Password").val() == "")
   {
        return;
   }
  $.ajax({
     url: '@Url.Action("Login")',
     data: {
     name:$("#Username").val(),
//serialize以键值对(Key/Value)的形式发送到服务器
     dataType: "json",
     type: "POST",
     success: function (data) {
     if (data.state == true) {
        window.location = '@Url.Action("Index","Home")';
             }
     else {
        alert("账号或者密码错误");
        $("#password").focus();
           }
            },
       error: function () {
          alert("登录出现问题,请联系系统管理员");
             }
          })
      }

4、角色的权限分配
角色权限设置在角色管理中实现,但是他获取的信息是模块表信息,设置成功过的信息保存在连接表中。
(1)权限树
所以先说在角色管理中的添加,主要是添加了一个权限管理的按钮,做了一个弹出表格,如下:

 <a id="btn" class="easyui-linkbutton" iconcls="icon-more" onclick="setRole();">设置权限</a>

接下来是他的事件:

 //设置权限
function setRole() {
  var rows = $("#roleList").datagrid("getSelections");
  if (rows.length!=1) {
      $.messager.alert("提示", "请选中一行", "info");
             return;
     }
      objModule.rid = rows[0].ID;
      //objModule.rid为全局变量
      $("#tree").tree({
         url: "@Url.Action("GetModuleTree","Module")",
         checkbox: true,
         type: "post",
         data: "",
         dataType: "Json",
         onLoadSuccess: function (data) {
               selectNodes(objModule.rid);
             }
         });
             $("#treedialog").dialog("open");
         }

为了方便,他调用的后台方法写在了"GetModuleTree","Module" 的模块管理的控制器中,如下:

 public ActionResult GetModuleTree()
 {
   return Json((Bll as ModuleBll).GetModuleTree(1));
 }

他继承的bll方法方法为:

 public List<ModuleTree> GetModuleTree(int id)
 {
   List<ModuleTree> mtl = new List<ModuleTree>();//声明一个list存数据
   List<Module> m = Dal.Search(x => x.M_ParentID == 0).ToList();
   foreach (var module in m)//将模型循环返回到树里边
     {
       ModuleTree mt = new ModuleTree();//声明一个模型树
       mt.id = module.ID;
       mt.text = module.M_name;
       BindChild(mt);
       mtl.Add(mt);
     }
       return mtl;
 }

(2)角色设置判定
他作用主要也是生成一个 模型树。在他的JS代码中,点击响应成功后会触发selectNodes事件,如下:

 function selectNodes(id) {
    $.ajax({
    url: "@Url.Action("GetModulesByRole","Module")?rid=" + id,
    dataType: "Json",
    type: "post",
    success: function (data) {
      for (var i = 0; i < data.length; i++) {
       var node = $("#tree").tree("find", data[i].toString());//找到指定的节点
       if (node != null) {
           if (node.children.length == 0) {
             $("#tree").tree("check", node.target);//选中该节点
                  }
                 }
               }
            }
       });
   }

他调用的方法为:

 public ActionResult GetModulesByRole(string rid)
   {
      int rId = 0;
      if (rid != null)
      {
        rId = int.Parse(rid);
      }
      return Json((Bll as ModuleBll).GetModulesByRoleID(rId));
   }

他主要是通过判断角色ID来给予权限,他继承的BLL为:

 public IEnumerable<int> GetModulesByRoleID(int rid)
 //通过角色ID获取模块列表
{
Role_ModuleBll powerBll = new Role_ModuleBll();
return powerBll.Search(x => x.Role.ID == rid).ToList().Select(x => x.Module.ID).ToList();
}

(3)保存权限

<div id="btnstree">
        <a class="easyui-linkbutton" iconcls="icon-redo" onclick="closeDialog();">取消</a>
        <a class="easyui-linkbutton" iconcls="icon-ok" onclick="saveRole();">保存</a>
    </div>

接下来是保存事件,当然记得把你的表格在初始化时进行设置。

function saveRole() {
            getCheckedNodes();
        };

响应的另外一个判断是否成功的事件。

 function getCheckedNodes() {
   var rId = objModule.rid;
   var nodes = $("#tree").tree("getChecked");
   var parentNodes = $("#tree").tree("getChecked", "indeterminate");
   var nodesArray = [];
   var strNodes = "";
   for (var i = 0; i < nodes.length; i++) {
        nodesArray.push(nodes[i].id);
     }
   for (var i = 0; i < parentNodes.length; i++) {
          nodesArray.push(parentNodes[i].id);
       }
   strNodes = nodesArray.join(',');
      $.ajax({
           url: "@Url.Action("SaveMoundle", "Module")",
           dataType: "Json",
           type:"post",
           data: { rId: rId, nodes: strNodes },
           success: function (data) {
           if (data == "ok") {
                  alert('设置成功');
               }
           else {
                   alert("设置失败");
               }
           $("#roleList").datagrid("load", {
                   M_ParentID: 0,
            });
                 $("#Tree").tree("reload");
                      closeDialog();
                    }
                });
             }

他的作用主要体现在表单上和模块树上,他调用了方法为:

 public ActionResult SaveMoundle(int rId, string nodes)
        {
            Role_ModuleBll urbll = new Role_ModuleBll();
            bool a = false;
            string[] strArrayIds = nodes.Split(',');//根据逗号分隔
            urbll.DeleteNoSave(x => x.R_ID == rId);
            if (strArrayIds.Length > 0 && strArrayIds[0] != "")
            {
                int[] intArrayIds = Array.ConvertAll<string, int>(strArrayIds, x => Convert.ToInt32(x));

                foreach (var item in intArrayIds)
                {
                    Role_Module us = new  Role_Module();
                    us.R_ID = rId;
                    us.M_ID = item;
                    urbll.AddNoSave(us);
                }
            }
            a = urbll.Save() > 0;
            if (a)
            {
                return Json("成功");
            }
            else
            {
                return Json("失败");
            }
        }

进行添加判断,如果成功保存到Role_Module中,失败则返回失败信息。

基本上功能就是这样,其中模块表的设置可能会麻烦一点,可以按照自己的需求做一下。


如果出现了明显错误请记得说明或者补充留言,谢谢。

posted on 2017-08-14 10:43  Grant-fu  阅读(264)  评论(0编辑  收藏  举报

导航