This question is locked. New answers and comments are not allowed.
I have a problem with the Authorize Attribute when Telerik attempts to render a tabstrip (likely similar to the problem described here)
The authorize attribute is created with a custom FilterProvider like following link demonstrates - DI - Filter Injection
At the bottom of the injection the project (its controllers and filters) are feed by Unity.
The attribute
The problem occurs within the namespace Telerik.Web.Mvc.Infrastructure.Implementation within ControllerAuthorization
The types are loaded within ControllerAuthorization correctly (to a extent) loading the CustomAuthorizeAttribute above, however the problem is that the filter provider is no longer being used to create the FilterAttribute leaving the two dependency Properties in CustomAuthorizeAttribute as null.
So the line: reflectedAuthorizeAttributeCache.GetAttribute(currentAuthorizationAttributeType);
returns the correct override, encapsulated as the IAuthorizeAttribute, but doest check if any properties can be resolved, hence the null problem.
Changing the method in my custom attribute so that it loads the correct files when needed is a solution when AuthorizeCore is called when subclassedAttribute.IsAuthorized(requestContext.HttpContext) is run:
Is there any better way for this to play nice?
Kind Regards,
Matthew Green
The authorize attribute is created with a custom FilterProvider like following link demonstrates - DI - Filter Injection
At the bottom of the injection the project (its controllers and filters) are feed by Unity.
The attribute
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]public class CustomAuthorizeAttribute : AuthorizeAttribute{ /// <summary> /// Feed by unity /// </summary> [Dependency] public IAuthorizationService AuthorizationService { get; set;} /// <summary> /// Feed by unity /// </summary> [Dependency] public ISiteInfo SiteInfo { get; set; } public bool AuthorizeByProduct { get; set; } //[Dependency] //public IUser User { get; set; } protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext) { if (!this.AuthorizationService.IsLoggedIn) return false; //test if available to current service if (SiteInfo.CurrentService != null) if (!AuthorizationService.BelongsToService(SiteInfo.CurrentService)) return false; //test if available to current product if (SiteInfo.CurrentProduct != null) if (!AuthorizationService.BelongsToProduct(SiteInfo.CurrentProduct)) return false; //test roles if (!this.AuthorizationService.HasRole(this.Roles.Split(','))) return false; if(AuthorizeByProduct) return this.AuthorizationService.BelongsToProduct(SiteInfo.CurrentProduct); return true; }}The problem occurs within the namespace Telerik.Web.Mvc.Infrastructure.Implementation within ControllerAuthorization
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "We will not allow if there is any exception.")] public bool IsAccessibleToUser(RequestContext requestContext, string controllerName, string actionName, RouteValueDictionary routeValues) { Guard.IsNotNull(requestContext, "requestContext"); Guard.IsNotNullOrEmpty(controllerName, "controllerName"); Guard.IsNotNullOrEmpty(actionName, "actionName"); IEnumerable<AuthorizeAttribute> authorizeAttributes = authorizeAttributeCache.GetAuthorizeAttributes(requestContext, controllerName, actionName, routeValues); bool allowed = true; foreach (AuthorizeAttribute authorizeAttribute in authorizeAttributes) { if (authorizeAttribute != null) { try { Type currentAuthorizationAttributeType = authorizeAttribute.GetType(); bool isDefaultAttribute = (currentAuthorizationAttributeType == defaultAuthorizeAttributeType); IAuthorizeAttribute subclassedAttribute = isDefaultAttribute ? new InternalAuthorizeAttribute() : // No need to use Reflection.Emit if it is the asp.net mvc built-in attribute authorizeAttribute is IAuthorizeAttribute ? authorizeAttribute as IAuthorizeAttribute : reflectedAuthorizeAttributeCache.GetAttribute(currentAuthorizationAttributeType); subclassedAttribute.Order = authorizeAttribute.Order; subclassedAttribute.Roles = authorizeAttribute.Roles; subclassedAttribute.Users = authorizeAttribute.Users; if (!isDefaultAttribute) { // Copy the remaining properties (if there is any) objectCopier.Copy(authorizeAttribute, subclassedAttribute, "Order", "Roles", "Users" /* Excluded properties */); } allowed = subclassedAttribute.IsAuthorized(requestContext.HttpContext); } catch { // do not allow on exception allowed = false; } if (!allowed) { break; } } } return allowed; }The types are loaded within ControllerAuthorization correctly (to a extent) loading the CustomAuthorizeAttribute above, however the problem is that the filter provider is no longer being used to create the FilterAttribute leaving the two dependency Properties in CustomAuthorizeAttribute as null.
So the line: reflectedAuthorizeAttributeCache.GetAttribute(currentAuthorizationAttributeType);
returns the correct override, encapsulated as the IAuthorizeAttribute, but doest check if any properties can be resolved, hence the null problem.
Changing the method in my custom attribute so that it loads the correct files when needed is a solution when AuthorizeCore is called when subclassedAttribute.IsAuthorized(requestContext.HttpContext) is run:
if(AuthorizationService == null) AuthorizationService = DependencyResolver.Current.GetService<IAuthorizationService>();if(SiteInfo == null) SiteInfo = DependencyResolver.Current.GetService<ISiteInfo>();Is there any better way for this to play nice?
Kind Regards,
Matthew Green