請先看: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、讀取時用到了反射,用於讀取控制器和方法,用返回值和類型做為過濾條件


