ASP.NET权限控制
这两周一直在给公司做官网,现在已经做好了。趁着周末有时间来梳理一下用到的主要知识点。其实核心技术就两点,第一就是后台权限控制,第二就是前台页面静态化(包括分页列表的静态化)。
第一步:后台权限数据表的建立
现在首先把我想到的权限控制的思路整理一下。权限控制本质是对访问的url路径的控制。本着这个思想我就形成了我的权限控制方法。这其中主要用到了四张表。如下图所示:
第一张表节点表,也就是你所建立的aspx文件的路径。这张表以父Id的形式递归展示。由于我的针对一个实体的CURD操作是通过如下形式进行的(显示和删除对应的文件格式是:../**List.aspx。增加和修改对应的文件格式是:../**Editor.aspx。),所以权限只能控制到实体而不能控制到CURD。
第二张表是角色表,角色和节点是多对多的关系。角色和用户是一对多的关系。现在有些权限控制角色和用户是多对多的关系。所以我这个权限控制的方法有些弊端。
第三张表是权限表。节点集合角色共同决定权限。
第四张表是用户表。我实际上是给角色分配权限。而用户又属于角色。所以用户可以获得对应角色的权限,进行登录后台。
第二步:网站后台对应表实体的创建,如下图:
第三步:后台其他文件的创建:
第四步:在节点表中将上图所有文件路径当作节点插入到节点表中,注意层次关系。如下图:
第五步:在角色列表中,给角色分配权限。实际上就是选择上图中的节点。如下图:
点击分配权限(先加载节点表中的所有节点,如果当前角色已经分配了权限,则先加载对应的权限),如下图:
第六步:在添加用户时会让选择对应的权限。到此时已经完全给用户分配了权限,接下来我们要将如何根据权限控制用户访问。
第七步:当用户登录时,根据用户的id获得对应的角色,从而获得对应的权限。根据权限递归生成左侧菜单树。因此左侧菜单栏也是根据权限动态绑定的。代码如下:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Web; 6 using System.Web.UI; 7 using System.Web.UI.WebControls; 8 9 public partial class Admin_Default : System.Web.UI.Page 10 { 11 12 protected string tree = ""; 13 protected string loginName = ""; 14 protected string admin = ""; 15 protected void Page_Load(object sender, EventArgs e) 16 { 17 var user= LoginValidate.Intance.ChekLogin(); 18 var role= ZXJB.DAL.DALFactory.RoleInfo.GetEntitys(c => c.RoleId == user.RoleId).FirstOrDefault(); 19 20 loginName = user.LoginName; 21 admin =role.RoleName+" ["+ user.LoginName+"]"; 22 var rights= ZXJB.DAL.DALFactory.RightInfo.GetEntitys(c => c.RoleId == user.RoleId); 23 24 List<ZXJB.Model.T_Node> nodes = new List<ZXJB.Model.T_Node>();//获得用户对应的所有节点 25 foreach (var item in rights) 26 { 27 nodes.Add(ZXJB.DAL.DALFactory.NodeInfo.GetEntitys(c => c.NodeId == item.NodeId).FirstOrDefault()); 28 } 29 nodes = nodes.OrderByDescending(c => c.SortId).ToList(); 30 tree = BindTreeView(0,nodes, ""); 31 } 32 //递归生成权限 33 string BindTreeView(int parent,List<ZXJB.Model.T_Node> nodes, string str) 34 { 35 36 StringBuilder sb = new StringBuilder(); 37 38 var childs = nodes.Where(c => c.ParentNodeId == parent).ToList(); //ZXJB.DAL.DALFactory.NodeInfo.GetEntitys(c => c.ParentNodeId == parent); 39 if (parent == 0) 40 { 41 sb.Append("<ul id=‘tree‘ class=\"easyui-tree\" >"); 42 } 43 else 44 { 45 sb.Append("<ul>"); 46 } 47 48 foreach (var cc in childs) 49 { 50 51 52 var ctwo = nodes.Where(c => c.ParentNodeId == parent).ToList(); //ZXJB.DAL.DALFactory.NodeInfo.GetEntitys(c => c.ParentNodeId == cc.NodeId); 53 54 if (cc.NodeUrl == "#") 55 { 56 sb.Append("<li>"); 57 } 58 else 59 { 60 sb.Append("<li id=‘" + cc.NodeUrl.Replace("/Admin/", "") + "‘>"); 61 } 62 if (ctwo.Count > 0) 63 { 64 sb.Append("<span> "); 65 } 66 67 sb.Append(cc.DisplayName); 68 69 if (ctwo.Count > 0) 70 { 71 sb.Append("</span>"); 72 } 73 74 if (ctwo.Count > 0) 75 { 76 77 sb.Append(BindTreeView(cc.NodeId,nodes, sb.ToString())); 78 79 } 80 sb.Append("</li>"); 81 } 82 sb.Append("</ul>"); 83 return sb.ToString(); 84 } 85 }
左侧功能菜单栏如图所示:
第八步:只是这样我们就可以算是完成了权限控制,但是这样还不行,如果用户不按照左侧的菜单栏操作后台,而是直接通过地址栏输入url访问怎么办。所以所我们要在每个文件的Page_Load事件中进行更加严格的权限验证。,所以说我们要写一个权限过滤器类库,如下。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.SessionState; 6 /// <summary> 7 /// LoginValidate 的摘要说明 8 /// </summary> 9 public class LoginValidate 10 { 11 public static readonly LoginValidate Intance = new LoginValidate(); 12 private LoginValidate() 13 { 14 15 } 16 public ZXJB.Model.T_User ChekLogin() 17 { 18 var session = HttpContext.Current.Session["currentUser"]; 19 if (session==null) 20 { 21 HttpContext.Current.Response.Redirect("~/AdLogin/Login.aspx?action=l",true); 22 } 23 24 List<ZXJB.Model.T_User> user = session as List<ZXJB.Model.T_User>; 25 return user[0]; 26 } 27 public void CheckRigth() 28 { 29 var user = ChekLogin(); 30 string url =HttpContext.Current.Request.Url.ToString(); 31 int tag = url.LastIndexOf("/"); 32 url = url.Substring(tag + 1).ToLower();//得到不包含文件夹的url 33 url = url.Substring(0, url.IndexOf(".aspx"));//去掉.aspx 34 // 35 int tag1 = url.IndexOf("list"); 36 if (tag1 > 0) 37 { 38 url = url.Substring(0, tag1);//取得List之前的字符串 39 } 40 int tag2 = url.IndexOf("editor"); 41 if (tag2 > 0) 42 { 43 url = url.Substring(0, tag2);//取得Editor之前的字符串 44 } 45 int tag3 = url.IndexOf("giveright"); 46 if (tag3 > 0) 47 { 48 url = url.Substring(0, tag3);//取得giveright之前的字符串 49 } 50 51 IList<string> urls = new List<string>(); 52 urls = GetRightUrl(user.RoleId); 53 int length = urls.Count; 54 int count = 0; 55 foreach (var item in urls) 56 { 57 if (item.Contains(url)) 58 { 59 count++; 60 } 61 } 62 if (count <= 0) 63 { 64 65 HttpContext.Current.Response.Redirect("~/AdLogin/Login.aspx?action=v"); 66 } 67 68 } 69 private IList<string> GetRightUrl(int roleId) 70 { 71 List<string> url = new List<string>(); 72 var list= ZXJB.DAL.DALFactory.RightInfo.GetEntitys(c => c.RoleId == roleId); 73 int count = list.Count; 74 if (count > 0) 75 { 76 foreach (var item in list) 77 { 78 var node = ZXJB.DAL.DALFactory.NodeInfo.GetEntitys(c => c.NodeId == item.NodeId).FirstOrDefault(); 79 if (node != null) 80 { 81 string urls = node.NodeUrl.ToLower(); 82 url.Add(urls); 83 } 84 else 85 { 86 87 } 88 } 89 } 90 else 91 { 92 return null; 93 94 } 95 return url; 96 97 } 98 }
第九步:我们在需要权限验证的每个文件的page_load中调用如下方法: LoginValidate.Intance.CheckRigth();//检查权限和登录状态(其实我们还可以在global文件中的Application_BeginRequest事件中进行统一验证,这个涉及到asp.net运行原理在这里暂不做说明)。
第十步:到这里我们就完成了一个简单的权限控制方法,接下来我将我的页面静态化特别是分页列表的静态化的原理及思路写下来。
原文:http://www.cnblogs.com/eggTwo/p/3525309.html