MVC小型商务网站实例(4)--MVC权限管理

ASP.NET MVC权限管理相关的文章实在太少了,真正在项目开发中实用的那就更少了。可能是大家都用Webform做后台开发吧。

转入正题:

模块实现功能:

角色管理 – 角色的增、删、改 ,给角色绑定用户和取消绑定

访问权限管理 – 访问权限的增、删、改

登录后的访问权限验证

表设计图:

 

ControllerAction 存放的是要设置访问权限的Controller和Action,ControllerActionRole 存放的是对应的角色可访问的Controller和Action,其它的表就不用多说了。

表的关联概述:

用户角色表(UserRole)在用户表(Use)与角色表(Role)中启连接绑定的关系,是一对多的一个用户只能有一个角色。

角色访问权限表(ControllerActionRole)在角色表(Role)与访问权限表(ControllerAction)中也是启连接绑定的关系,是一对多的,一个角色可以有多个访问权限。

设计思路:

用户登录时从数据库中取得对应角色用Session保存,再用Filter来验证用户的访问权限。为了提高效率可以把与访问权限相关的数据缓存起来。

实现代码:

先写一个访问权限的判断的Service

public static class AccountService
{
private static SouthShopEntities1 Service { get { return BaseRepository.sse; } }
private static IMsCache MsCache { get { return (IMsCache)MvcApplication.Container["msCache"]; } }

public static bool IsAllowed(Role role, string controllerName, string actionName)
{
IEnumerable
<ControllerAction> cas;
if (!MsCache.TryGet("ControllerActions", out cas))
{
try
{
cas
= Service.ControllerActions.ToList();
var _ExpireTime
= DateTime.Now.AddMinutes(30);//指定30分钟后过期
MsCache.Set<IEnumerable<ControllerAction>>("ControllerActions", cas, _ExpireTime);
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}


// 获取对应的controller
var controller = (cas.Where(c => c.Name == controllerName)).Where(c => c.IsControler).Select(c => c).FirstOrDefault();
if (controller != null)
{
// 获取对应的action
var controllerAction = ((cas.Where(c => c.Name == actionName)).Where(c => c.IsControler == false)).Where(c => c.ControlerName == controllerName).Select(c => c).FirstOrDefault();
return controllerAction == null ? IsAllowed(role, controller) : IsAllowed(role, controllerAction);
}

return false;
}

public static bool IsAllowed(Role role, ControllerAction controllerAction)
{
IEnumerable
<ControllerActionRole> cars;
string userCAR = role.RoleId + "_ControllerActionRole";
if (!MsCache.TryGet(userCAR, out cars))
{
try
{
cars
= Service.ControllerActionRoles.Where(c => c.RoleId == role.RoleId).Select(c => c).ToList();
var _ExpireTime
= DateTime.Now.AddMinutes(30);//指定30分钟后过期
MsCache.Set<IEnumerable<ControllerActionRole>>(userCAR, cars, _ExpireTime);
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}


// 允许没有角色的:也就是说允许所有人,包括没有登录的用户
if (controllerAction.IsAllowedNoneRoles)
{
return true;
}

// 允许所有角色:只要有角色,就可以访问
if (controllerAction.IsAllowedAllRoles)
{
if (role == null)
{
return false;
}

return true;
}

// 选出action对应的角色
var roles = cars.Where(c=>c.ControlerActionId==controllerAction.ControllerActionId).Select(c=>c).ToList();
if (roles.Count == 0)
{
// 角色数量为0,也就是说没有定义访问规则,默认允许访问
return true;
}

//查找有没有当前用户所对应的角色
var HavedRolesids = roles.Find(c=>c.RoleId==role.RoleId);
if (HavedRolesids == null)
{
//找不到当前用户所对应的角色,不允许访问
return false;
}

//只有允许旂角色才可以访问
if (HavedRolesids.IsAllowed)
{
return true;
}

return false;
}
}

 

再实现访问权限的Filter ,在里面调用上面的Service。

public class RoleAuthorizeAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
bool isAllowed = false;
var role
= filterContext.HttpContext.Session["CurrentRole"] as Role;
var controller
= filterContext.RouteData.Values["controller"].ToString();
var action
= filterContext.RouteData.Values["action"].ToString();

if (role != null)
isAllowed
= AccountService.IsAllowed(role, controller, action);

if (!isAllowed)
{
filterContext.RequestContext.HttpContext.Response.Write(
"无权访问");
filterContext.RequestContext.HttpContext.Response.End();
}

}
}

如果是整个Controller下都需要身份验证的话,那就把这个Filter放到外层的Controller上。这样就不用在每个Action上都写了。如:

[RoleAuthorize]
public class AdminController : Controller
{
public ActionResult Index()
{
return View();
}

}

这样就搞定了,对于权限相关的数据表的增、删、改我这里就不废话了。



posted on 2011-03-19 16:22  Ω元素  阅读(3278)  评论(6编辑  收藏  举报

导航