我已经实施了一个涉及Rhino.Security的解决方案来管理用户/角色/权限 由于我想检查用户是否有权访问控制器操作,因此我实现了自定义操作过滤器:
public class AuthorizationAttribute : ActionFilterAttribute
{
CustomPrincipal currentPrincipal = (CustomPrincipal)filterContext.HttpContext.User;
var actionName = filterContext.ActionDescriptor.ActionName;
var controllerName = filterContext.Controller.GetType().Name;
var operation = string.Format("/{0}/{1}", controllerName, actionName);
if (!securityService.CheckAuthorizationOnOperation(currentPrincipal.Code, operation))
{
filterContext.Controller.TempData["ErrorMessage"] = string.Format("You are not authorized to perform operation: {0}", operation);
filterContext.Result = new HttpUnauthorizedResult();
}
}
CheckAuthorizationOnOperation 调用Rhino.Security来检查是否允许用户执行指定的操作:
AuthorizationService.IsAllowed(user, operation);
一切正常但我注意到,当执行 IsAllowed 调用的查询时,从不会触发二级缓存。
我已经调查过,我已经看到框架( Rhino.Security )使用 DetachedCriteria 。这些是2个程序:
public Permission[] GetGlobalPermissionsFor(IUser user, string operationName)
{
string[] operationNames = Strings.GetHierarchicalOperationNames(operationName);
DetachedCriteria criteria = DetachedCriteria.For<Permission>()
.Add(Expression.Eq("User", user)
|| Subqueries.PropertyIn("UsersGroup.Id",
SecurityCriterions.AllGroups(user).SetProjection(Projections.Id())))
.Add(Expression.IsNull("EntitiesGroup"))
.Add(Expression.IsNull("EntitySecurityKey"))
.CreateAlias("Operation", "op")
.Add(Expression.In("op.Name", operationNames));
return FindResults(criteria);
}
private Permission[] FindResults(DetachedCriteria criteria)
{
ICollection<Permission> permissions = criteria.GetExecutableCriteria(session)
.AddOrder(Order.Desc("Level"))
.AddOrder(Order.Asc("Allow"))
.SetCacheable(true)
.List<Permission>();
return permissions.ToArray();
}
如您所见 FindResults 使用 SetCacheable 。
每次刷新页面时,我的动作过滤器都会执行过程并再次执行查询,忽略缓存(第二级)。 由于我广泛使用缓存和所有其他调用正常工作,我想了解为什么这个调用不能按预期工作。
进行一些研究我注意到只有在我调用该函数两次时才使用二级缓存:
SecurityService.CheckAuthorizationOnOperation(currentPrincipal.Code, "/Users/Edit");
SecurityService.CheckAuthorizationOnOperation(currentPrincipal.Code, "/Users/Edit");
似乎这种特殊情况的缓存只有在我使用相同的会话(nHibernate)时才有效。 有没有人可以帮我弄清楚发生了什么?
更新:
答案 0 :(得分:1)
答案 1 :(得分:1)
此框架存在问题。 我在Google Groups上打开了一个问题,每个人都知道,但似乎框架已被遗忘。