ユーザー/役割/権限を管理するために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によって呼び出されたクエリが実行されたときに、第2レベルのキャッシュがヒットしないことに気付きました。
調査したところ、フレームワーク(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を使用しています。
ページを更新するたびに、アクションフィルターがプロシージャを実行し、キャッシュを無視してクエリが再度実行されます(第2レベル)。私はキャッシュを広範囲に使用し、他のすべての呼び出しは適切に機能するため、これが期待どおりに機能しない理由を理解したいと思います。
調査を行ったところ、関数を2回呼び出した場合にのみ、第2レベルのキャッシュが使用されることに気付きました。
SecurityService.CheckAuthorizationOnOperation(currentPrincipal.Code, "/Users/Edit");
SecurityService.CheckAuthorizationOnOperation(currentPrincipal.Code, "/Users/Edit");
この特定の状況のキャッシュは、同じセッション(nHibernate)を使用している場合にのみ機能するようです。何が起こっているのかを理解するのを手伝ってくれる人はいますか?
アップデート: