請先看:http://www.cnblogs.com/xiaoqi/archive/2011/01/24/1942880.html
權限控制需要將控制器和Action信息寫入到數據庫,手動添加的話比較麻煩,有沒有更簡單的辦法呢?
那就用反射把吧,我們可以借助代碼注釋( 將權限控制的詳細用xml注釋的方式寫到代碼里)+反射技術來巧妙的實現
同時,還可以用來作后台導航哦
效果篇
/// <IsShow>True</IsShow>
/// <IsHeader>True</IsHeader>
/// <Title>個人信息</Title>
/// <IsAllowedNoneRoles>False</IsAllowedNoneRoles>
/// <IsAllowedAllRoles>False</IsAllowedAllRoles>
class UserInfoController{}
后台對應的效果
XML注釋說明
/// <IsShow>True</IsShow> 表示是否在導航菜單顯示
/// <IsHeader>False</IsHeader> 表示是否是導航標題 通常用於Controler類
/// <Title>選擇用戶</Title> 標題
/// <IsAllowedNoneRoles>False</IsAllowedNoneRoles> 是否允許匿名訪問
/// <IsAllowedAllRoles>False</IsAllowedAllRoles> 是否允許所有登錄用戶訪問
讀取XML注釋
首先配置MVC項目,生成XML文件
屬性 --生成 -- 輸出
在網站啟動的時候,執行初始化任務
// 執行啟動任務 IoC.ResolveAll().ForEach(t => t.Execute());
相關代碼:
/// /// 啟動任務 /// public interface IBootstrapperTask { void Execute(); }
具體實現代碼:
public class InitSystemConfig : IBootstrapperTask { private readonly IDomainObjectFactory _factory; private readonly IUserRepository _userRepository; private readonly IRoleRepository _roleRepository; private readonly IResourceRepository _resourceRepository; private readonly DefaultRole[] _defaultRoles; private readonly DefaultUser[] _defaultUsers; private readonly DefaultResource[] _defaultResources; public InitSystemConfig(IDomainObjectFactory factory, IUserRepository userRepository, IRoleRepository roleRepository, IResourceRepository resourceRepository, DefaultRole[] defaultRoles, DefaultUser[] defaultUsers, DefaultResource[] defaultResources) { Check.Argument.IsNotNull(factory, "factory"); Check.Argument.IsNotNull(userRepository, "userRepository"); Check.Argument.IsNotNull(roleRepository, "roleRepository"); Check.Argument.IsNotNull(defaultRoles, "defaultRoles"); Check.Argument.IsNotNull(defaultUsers, "defaultUsers"); _factory = factory; _userRepository = userRepository; _roleRepository = roleRepository; _resourceRepository = resourceRepository; _defaultRoles = defaultRoles; _defaultUsers = defaultUsers; _defaultResources = defaultResources; } public void Execute() { CreateResourceIfNotrExist(); CreateDefaultController(); CreateRoleIfNotExist(); CreateUserIfNotrExist(); } /// /// 為沒有配置信息的控制器和Action創建記錄,默認設為所有用戶可訪問 /// void CreateDefaultController() { using (IUnitOfWork unitOfWork = UnitOfWork.Begin()) { IConfigurationManager configurationManager = IoC.Resolve(); var assemblyName = configurationManager.AppSettings["WebAssemblyName"]; if (string.IsNullOrEmpty(assemblyName)) { assemblyName = "MarkerPlatform.Web"; } Assembly assembly = Assembly.Load(assemblyName); Type[] types = assembly.GetTypes(); var assemblyXml = HttpContext.Current.Server.MapPath("~/bin/" + assemblyName + ".xml"); XmlDocument assembleDoc = new XmlDocument(); if (File.Exists(assemblyXml)) assembleDoc.Load(assemblyXml); foreach (Type type in types) { if (type.BaseType != null) { if (type.Name.Contains("Controller") && type.BaseType.Name == "BaseController") { // 查詢數據庫有沒有controler信息 var controllerName = type.Name.Replace("Controller", ""); var dbController = _resourceRepository.FindController(controllerName); // controller為空或者允許所有人訪問並且不允許匿名用戶訪問 // 如果允許匿名用戶訪問,則這個控制器默認所有Action均可訪問 if (dbController == null || dbController.IsAllowedAllRoles && !dbController.IsAllowedNoneRoles) { if (dbController == null) { // 獲取controller dbController = GetController(assembleDoc, type, controllerName); if (dbController != null) _resourceRepository.Add(dbController); } //獲取方法信息 MethodInfo[] myMethodInfo = type.GetMethods(); try { foreach (var methodInfo in myMethodInfo) { if (methodInfo.ReturnType.Name == "ActionResult") { var actionName = methodInfo.Name; var dbresource = _resourceRepository.FindAction(controllerName, actionName); if (dbresource == null) { // 默認設為所有用戶可訪問 dbresource = GetDbresource(assembleDoc, controllerName, methodInfo, actionName); if (dbresource != null) _resourceRepository.Add(dbresource); } } } } catch (Exception ex) { Console.Write(ex); } } } } } unitOfWork.Commit(); } } /// /// 為方法創建實體 /// /// /// /// /// /// private IResource GetDbresource(XmlDocument assembleDoc, string controllerName, MethodInfo methodInfo, string actionName) { IResource dbresource; dbresource = _factory.CreateResource(actionName, controllerName, false, false, true); var path = "M:" + methodInfo.DeclaringType.FullName + "." + methodInfo.Name; XmlNode node = GetNode(assembleDoc, path); if (node == null) { dbresource.IsHeader = false; dbresource.IsShow = false; dbresource.Title = controllerName + "/" + actionName; } else { var child = node.SelectSingleNode("IsShow"); dbresource.IsShow = child != null && bool.Parse(child.InnerText); child = node.SelectSingleNode("IsHeader"); dbresource.IsHeader = child != null && bool.Parse(child.InnerText); child = node.SelectSingleNode("Title"); if (child == null) child = node.SelectSingleNode("summary"); dbresource.Title = child != null ? child.InnerText.Trim() : ""; if (string.IsNullOrEmpty(dbresource.Title)) { dbresource.Title = controllerName + "/" + actionName; } child = node.SelectSingleNode("IsAllowedAllRoles"); dbresource.IsAllowedAllRoles = child != null && bool.Parse(child.InnerText); child = node.SelectSingleNode("IsAllowedNoneRoles"); dbresource.IsAllowedNoneRoles = child != null && bool.Parse(child.InnerText); } return dbresource; } /// /// 為控制器創建實體 /// /// /// /// /// private IResource GetController(XmlDocument assembleDoc, Type type, string controllerName) { IResource dbController; XmlNode controllerNode = GetNode(assembleDoc, "T:" + type.FullName); // 默認匿名用戶不能訪問 登錄用戶均可訪問 dbController = _factory.CreateResource(controllerName, controllerName, true, false, true); if (controllerNode != null) { var child = controllerNode.SelectSingleNode("IsShow"); dbController.IsShow = child != null && bool.Parse(child.InnerText); child = controllerNode.SelectSingleNode("IsShow"); dbController.IsHeader = child != null && bool.Parse(child.InnerText); child = controllerNode.SelectSingleNode("Title"); if (child == null) child = controllerNode.SelectSingleNode("summary"); dbController.Title = child != null ? child.InnerText.Trim() : ""; if (string.IsNullOrEmpty(dbController.Title.Trim())) { dbController.Title = controllerName; } child = controllerNode.SelectSingleNode("IsAllowedAllRoles"); dbController.IsAllowedAllRoles = child != null && bool.Parse(child.InnerText); child = controllerNode.SelectSingleNode("IsAllowedAllRoles"); dbController.IsAllowedAllRoles = child != null && bool.Parse(child.InnerText); } else { dbController.IsHeader = false; dbController.IsShow = false; dbController.Title = controllerName; } return dbController; } private XmlNode GetNode(XmlDocument assembleDoc, string name) { var nodes = assembleDoc.SelectNodes("/doc/members/member"); XmlNode node = null; if (nodes != null) foreach (XmlNode xmlNode in nodes) { if (xmlNode.Attributes != null) if (xmlNode.Attributes["name"].Value.Contains((name))) { node = xmlNode; break; } } return node; } void CreateRoleIfNotExist() { using (IUnitOfWork unitOfWork = UnitOfWork.Begin()) { foreach (var role in _defaultRoles) { var dbRole = _roleRepository.GetByName(role.Name); if (dbRole == null) { dbRole = _factory.CreateRole(role.Name, role.Description); // 添加資源 var resources = role.Resources.Split(','); foreach (var resourceName in resources) { var defaultResource = IoC.Resolve(resourceName); if (defaultResource != null) { if (String.IsNullOrEmpty(defaultResource.Name)) { continue; } var resource = defaultResource.IsController ? _resourceRepository.FindController(defaultResource.Name) : _resourceRepository.FindAction(defaultResource.ControllName, defaultResource.Name); if (resource != null) { dbRole.AddResouce(resource); } } } _roleRepository.Add(dbRole); } } unitOfWork.Commit(); } } void CreateUserIfNotrExist() { using (IUnitOfWork unitOfWork = UnitOfWork.Begin()) { foreach (var user in _defaultUsers) { // account 為email var dbUser = _userRepository.FindByAccountName(user.Email); if (dbUser == null) { dbUser = _factory.CreateUser(user.Email, user.Name, user.Password, " ", " "); dbUser.Gender = user.Gender; var role = _roleRepository.GetByName(user.Role.Name); if (role != null) { dbUser.AddToRole(role); } _userRepository.Add(dbUser); } } unitOfWork.Commit(); } } void CreateResourceIfNotrExist() { using (IUnitOfWork unitOfWork = UnitOfWork.Begin()) { foreach (var resource in _defaultResources) { var dbresource = resource.IsController ? _resourceRepository.FindController(resource.Name) : _resourceRepository.FindAction(resource.ControllName, resource.Name); if (dbresource == null) { dbresource = _factory.CreateResource(resource.Name, resource.ControllName, resource.IsController, resource.IsAllowedNoneRoles, resource.IsAllowedAllRoles); dbresource.IsHeader = resource.IsHeader; dbresource.IsShow = resource.IsShow; dbresource.Title = resource.Title; _resourceRepository.Add(dbresource); } } unitOfWork.Commit(); } } }
代碼說明
1、需要在系統啟動時執行,放在Global.asax中即可
2、每次加載時只創建不存在的記錄(CreateResourceIfNotrExist)
3、讀取時用到了反射,用於讀取控制器和方法,用返回值和類型做為過濾條件