using System; using System.Security.Claims; using System.Web; using System.Web.Mvc; using AuthorizationContext = System.Web.Mvc.AuthorizationContext; namespace Kreta.Web.Security { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] public class MvcResourceAuthorizeAttribute : AuthorizeAttribute { private string resource; private string action; private string[] additionalResources; public MvcResourceAuthorizeAttribute() { } public MvcResourceAuthorizeAttribute(string action, string resource, params string[] additionalResources) { this.action = action; this.resource = resource; this.additionalResources = additionalResources; } public override void OnAuthorization(AuthorizationContext filterContext) { if (AuthorizeCore(filterContext.HttpContext)) { HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache; cache.SetProxyMaxAge(new TimeSpan(0L)); cache.AddValidationCallback(new HttpCacheValidateHandler(CacheValidateHandler), null); } else { HandleUnauthorizedRequest(filterContext); } } protected override bool AuthorizeCore(HttpContextBase httpContext) { return CheckAccess(action, resource, additionalResources); } public bool IsAuthorized(HttpContextBase httpContext) { return AuthorizeCore(httpContext); } protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { filterContext.Result = new HttpUnauthorizedResult(); } protected override HttpValidationStatus OnCacheAuthorization(HttpContextBase httpContext) { return !AuthorizeCore(httpContext) ? HttpValidationStatus.IgnoreThisRequest : HttpValidationStatus.Valid; } private void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus) { validationStatus = OnCacheAuthorization(new HttpContextWrapper(context)); } private static bool CheckAccess(string claimType, string resource, params string[] additionalResources) { var principal = HttpContext.Current.User as ClaimsPrincipal; return CheckAccess( principal, claimType, resource, additionalResources); } private static bool CheckAccess(ClaimsPrincipal principal, string claimType, string resource, params string[] additionalResources) { bool access = resource == null ? principal.ClaimExists(claimType) : principal.ClaimExists(claimType, new[] { resource }); return access; } } }