diff --git a/src/MvcSiteMapProvider/CodeAsConfiguration/SimpleInjector/DI/SimpleInjector/MvcSiteMapProviderContainerInitializer.cs b/src/MvcSiteMapProvider/CodeAsConfiguration/SimpleInjector/DI/SimpleInjector/MvcSiteMapProviderContainerInitializer.cs index a60ffad7..0f72ab93 100644 --- a/src/MvcSiteMapProvider/CodeAsConfiguration/SimpleInjector/DI/SimpleInjector/MvcSiteMapProviderContainerInitializer.cs +++ b/src/MvcSiteMapProvider/CodeAsConfiguration/SimpleInjector/DI/SimpleInjector/MvcSiteMapProviderContainerInitializer.cs @@ -109,14 +109,6 @@ public static void SetUp(Container container) ())); // Configure Security - container.RegisterSingle(() => new AuthorizeAttributeAclModule( - container.GetInstance(), - container.GetInstance(), - container.GetInstance(), - container.GetInstance(), - container.GetInstance(), - container.GetInstance())); - container.RegisterAll(typeof(AuthorizeAttributeAclModule), typeof(XmlRolesAclModule)); container.RegisterSingle(() => new CompositeAclModule(container.GetAllInstances().ToArray())); diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/DI/SiteMapFactoryContainer.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/DI/SiteMapFactoryContainer.cs index 10aa524a..5dfc0d73 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/DI/SiteMapFactoryContainer.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/DI/SiteMapFactoryContainer.cs @@ -60,10 +60,8 @@ private IAclModule ResolveAclModule() return new CompositeAclModule( new AuthorizeAttributeAclModule( this.mvcContextFactory, - new ObjectCopier(), new ControllerDescriptorFactory(), new ControllerBuilderAdaptor(ControllerBuilder.Current), - new AuthorizeAttributeBuilder(), new GlobalFilterProvider() ), new XmlRolesAclModule( diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/MvcSiteMapProvider.csproj b/src/MvcSiteMapProvider/MvcSiteMapProvider/MvcSiteMapProvider.csproj index f5386d75..46584a2a 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/MvcSiteMapProvider.csproj +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/MvcSiteMapProvider.csproj @@ -142,12 +142,13 @@ - + + @@ -174,7 +175,6 @@ - @@ -242,12 +242,8 @@ - - - - diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/Reflection/IObjectCopier.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/Reflection/IObjectCopier.cs deleted file mode 100644 index 3d188546..00000000 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/Reflection/IObjectCopier.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace MvcSiteMapProvider.Reflection -{ - /// - /// Contract for the object copier. - /// - public interface IObjectCopier - { - void Copy(object source, object destination, params string[] excludedMembers); - } -} diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/Reflection/ObjectCopier.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/Reflection/ObjectCopier.cs deleted file mode 100644 index 0013a481..00000000 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/Reflection/ObjectCopier.cs +++ /dev/null @@ -1,57 +0,0 @@ -// (c) Copyright 2002-2010 Telerik -// This source is subject to the GNU General Public License, version 2 -// See http://www.gnu.org/licenses/gpl-2.0.html. -// All other rights reserved. - -// Modified by Shad Storhaug - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; - -namespace MvcSiteMapProvider.Reflection -{ - /// - /// ObjectCopier - /// - public class ObjectCopier - : IObjectCopier - { - public void Copy(object source, object destination, params string[] excludedMembers) - { - bool hasExcludedMembers = ((excludedMembers != null) && (excludedMembers.Length > 0)); - Type sourceType = source.GetType(); - - IEnumerable fields = - sourceType.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetField | BindingFlags.SetField).Where(field => !field.IsInitOnly); - - if (hasExcludedMembers) - { - fields = fields.Where(field => !excludedMembers.Any(name => field.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase))); - } - - foreach (FieldInfo field in fields) - { - field.SetValue(destination, field.GetValue(source)); - } - - IEnumerable properties = - sourceType.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where( - p => p.CanRead && p.GetGetMethod() != null && p.CanWrite && p.GetSetMethod() != null); - - if (hasExcludedMembers) - { - properties = properties.Where(property => !excludedMembers.Any(name => property.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase))); - } - - foreach (PropertyInfo property in properties) - { - if (property.GetIndexParameters().Length == 0) - { - property.SetValue(destination, property.GetValue(source, null), null); - } - } - } - } -} \ No newline at end of file diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/Security/AuthorizeAttributeAclModule.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/Security/AuthorizeAttributeAclModule.cs index a9f78926..02afb12a 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/Security/AuthorizeAttributeAclModule.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/Security/AuthorizeAttributeAclModule.cs @@ -7,54 +7,41 @@ using System.Web.Routing; using MvcSiteMapProvider.Web.Mvc; using MvcSiteMapProvider.Web.Mvc.Filters; -using MvcSiteMapProvider.Reflection; namespace MvcSiteMapProvider.Security { /// - /// AuthorizeAttributeAclModule class + /// An ACL module that determines whether the current user has access to a given node based on the MVC AuthorizeAttribute. /// public class AuthorizeAttributeAclModule : IAclModule { public AuthorizeAttributeAclModule( IMvcContextFactory mvcContextFactory, - IObjectCopier objectCopier, IControllerDescriptorFactory controllerDescriptorFactory, IControllerBuilder controllerBuilder, - IAuthorizeAttributeBuilder authorizeAttributeBuilder, IGlobalFilterProvider filterProvider ) { if (mvcContextFactory == null) throw new ArgumentNullException("mvcContextFactory"); - if (objectCopier == null) - throw new ArgumentNullException("objectCopier"); if (controllerDescriptorFactory == null) throw new ArgumentNullException("controllerDescriptorFactory"); if (controllerBuilder == null) throw new ArgumentNullException("controllerBuilder"); - if (authorizeAttributeBuilder == null) - throw new ArgumentNullException("authorizeAttributeBuilder"); if (filterProvider == null) throw new ArgumentNullException("filterProvider"); this.mvcContextFactory = mvcContextFactory; - this.objectCopier = objectCopier; this.controllerDescriptorFactory = controllerDescriptorFactory; this.controllerBuilder = controllerBuilder; - this.authorizeAttributeBuilder = authorizeAttributeBuilder; this.filterProvider = filterProvider; } protected readonly IMvcContextFactory mvcContextFactory; - protected readonly IObjectCopier objectCopier; protected readonly IControllerDescriptorFactory controllerDescriptorFactory; protected readonly IControllerBuilder controllerBuilder; - protected readonly IAuthorizeAttributeBuilder authorizeAttributeBuilder; protected readonly IGlobalFilterProvider filterProvider; - - private static readonly Type defaultAuthorizeAttributeType = typeof(AuthorizeAttribute); #region IAclModule Members @@ -171,24 +158,19 @@ protected virtual bool VerifyControllerAttributes(ISiteMapNode node, Type contro if (actionDescriptor == null) return true; - // Fixes #130 - Check whether we have an AllowAnonymous Attribute - var ignoreAuthorization = this.HasAllowAnonymousAttribute(actionDescriptor); - if (ignoreAuthorization) - return true; - // Verify security var authorizeAttributes = this.GetAuthorizeAttributes(actionDescriptor, controllerContext); - return this.VerifyAuthorizeAttributes(authorizeAttributes, controllerContext); + return this.VerifyAuthorizeAttributes(authorizeAttributes, controllerContext, actionDescriptor); } - protected virtual bool VerifyAuthorizeAttributes(IEnumerable authorizeAttributes, ControllerContext controllerContext) + protected virtual bool VerifyAuthorizeAttributes(IEnumerable authorizeAttributes, ControllerContext controllerContext, ActionDescriptor actionDescriptor) { // Verify all attributes foreach (var authorizeAttribute in authorizeAttributes) { try { - var authorized = this.VerifyAuthorizeAttribute(authorizeAttribute, controllerContext); + var authorized = this.VerifyAuthorizeAttribute(authorizeAttribute, controllerContext, actionDescriptor); if (!authorized) return false; } @@ -221,53 +203,13 @@ protected virtual IEnumerable GetAuthorizeAttributes(ActionD } #endif -#if MVC2 - protected virtual bool HasAllowAnonymousAttribute(ActionDescriptor actionDescriptor) - { - return false; - } -#else -#if MVC3 - protected virtual bool HasAllowAnonymousAttribute(ActionDescriptor actionDescriptor) + protected virtual bool VerifyAuthorizeAttribute(AuthorizeAttribute authorizeAttribute, ControllerContext controllerContext, ActionDescriptor actionDescriptor) { - return false; - } -#else - protected virtual bool HasAllowAnonymousAttribute(ActionDescriptor actionDescriptor) - { - var allowAnonymousType = typeof(AllowAnonymousAttribute); - return (actionDescriptor.IsDefined(allowAnonymousType, true) || - actionDescriptor.ControllerDescriptor.IsDefined(allowAnonymousType, true)); - } -#endif -#endif - - protected virtual bool VerifyAuthorizeAttribute(AuthorizeAttribute authorizeAttribute, ControllerContext controllerContext) - { - // Reasoning for using Reflection and AuthorizeAttribute rather than IAuthorizationFilter - // http://weblogs.asp.net/rashid/archive/2009/09/06/asp-net-mvc-and-authorization-and-monkey-patching.aspx - - var currentAuthorizationAttributeType = authorizeAttribute.GetType(); - var isDefaultAttribute = (currentAuthorizationAttributeType == defaultAuthorizeAttributeType); - - var subclassedAttribute = - isDefaultAttribute ? - new InternalAuthorizeAttribute() : // No need to use Reflection.Emit when ASP.NET MVC built-in attribute is used - authorizeAttribute is IAuthorizeAttribute ? - authorizeAttribute as IAuthorizeAttribute : - authorizeAttributeBuilder.Build(currentAuthorizationAttributeType).Invoke(new object[0]) as IAuthorizeAttribute; - - subclassedAttribute.Order = authorizeAttribute.Order; - subclassedAttribute.Roles = authorizeAttribute.Roles; - subclassedAttribute.Users = authorizeAttribute.Users; - - if (!isDefaultAttribute) - { - // Copy remaining properties - objectCopier.Copy(authorizeAttribute, subclassedAttribute, "Order", "Roles", "Users"); - } - - return subclassedAttribute.IsAuthorized(controllerContext.HttpContext); + var authorizationContext = new AuthorizationContext(controllerContext, actionDescriptor); + authorizeAttribute.OnAuthorization(authorizationContext); + if (authorizationContext.Result != null) + return false; + return true; } protected virtual ActionDescriptor GetActionDescriptor(string action, ControllerDescriptor controllerDescriptor, ControllerContext controllerContext) diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/Security/AuthorizeAttributeBuilder.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/Security/AuthorizeAttributeBuilder.cs deleted file mode 100644 index 7ce355dd..00000000 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/Security/AuthorizeAttributeBuilder.cs +++ /dev/null @@ -1,130 +0,0 @@ -// (c) Copyright Telerik Corp. -// This source is subject to the Microsoft Public License. -// See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL. -// All other rights reserved. - -// Modified by Maarten Balliauw - http://mvcsitemap.codeplex.com - -using System; -using System.Reflection; -using System.Reflection.Emit; -using System.Web; - -namespace MvcSiteMapProvider.Security -{ - /// - /// AuthorizeAttributeBuilder class - /// - public class AuthorizeAttributeBuilder - : IAuthorizeAttributeBuilder - { - private static readonly Type AuthorizeAttributeType = typeof(IAuthorizeAttribute); - private static readonly ModuleBuilder Module = CreateModuleBuilder(); - - /// - /// Builds the specified parent type. - /// - /// Type of the parent. - /// Constructor information. - public ConstructorInfo Build(Type parentType) - { - var typeName = "$" + parentType.FullName.Replace(".", string.Empty); - - var definedType = Module.GetType(typeName); - if (definedType == null) - { - var typeBuilder = Module.DefineType(typeName, TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit, parentType, new[] { AuthorizeAttributeType }); - typeBuilder.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName); - typeBuilder.AddInterfaceImplementation(AuthorizeAttributeType); - - WriteProperty(parentType, typeBuilder, "Order", typeof(int)); - WriteProperty(parentType, typeBuilder, "Roles", typeof(string)); - WriteProperty(parentType, typeBuilder, "Users", typeof(string)); - WriteIsAuthorized(parentType, typeBuilder); - - definedType = typeBuilder.CreateType(); - } - - return definedType.GetConstructor(Type.EmptyTypes); - } - - /// - /// Writes the property. - /// - /// Type of the parent. - /// The builder. - /// The name. - /// The type. - private static void WriteProperty(Type parentType, TypeBuilder builder, string name, Type type) - { - const BindingFlags BindingFlag = BindingFlags.Public | BindingFlags.Instance; - const MethodAttributes MethodAttribute = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.NewSlot; - - string getName = "get_" + name; - string setName = "set_" + name; - - MethodInfo parentGetMethod = parentType.GetMethod(getName, BindingFlag); - MethodBuilder implementedGetMethod = builder.DefineMethod(getName, MethodAttribute, type, Type.EmptyTypes); - ILGenerator getIl = implementedGetMethod.GetILGenerator(); - getIl.Emit(OpCodes.Ldarg_0); - getIl.Emit(OpCodes.Call, parentGetMethod); - getIl.Emit(OpCodes.Ret); - - MethodInfo interfaceGetMethod = AuthorizeAttributeType.GetMethod(getName, BindingFlag); - builder.DefineMethodOverride(implementedGetMethod, interfaceGetMethod); - - MethodInfo parentSetMethod = parentType.GetMethod(setName, BindingFlag); - MethodBuilder implementedSetMethod = builder.DefineMethod(setName, MethodAttribute, typeof(void), new[] { type }); - ILGenerator setIl = implementedSetMethod.GetILGenerator(); - setIl.Emit(OpCodes.Ldarg_0); - setIl.Emit(OpCodes.Ldarg_1); - setIl.Emit(OpCodes.Call, parentSetMethod); - setIl.Emit(OpCodes.Ret); - - MethodInfo interfaceSetMethod = AuthorizeAttributeType.GetMethod(setName, BindingFlag); - builder.DefineMethodOverride(implementedSetMethod, interfaceSetMethod); - } - - /// - /// Writes the is authorized. - /// - /// Type of the parent. - /// The builder. - private static void WriteIsAuthorized(Type parentType, TypeBuilder builder) - { - var protectedMethod = parentType.GetMethod("AuthorizeCore", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod); - var implementedMethod = builder.DefineMethod("IsAuthorized", MethodAttributes.Public | MethodAttributes.Virtual, typeof(bool), new[] { typeof(HttpContextBase) }); - var il = implementedMethod.GetILGenerator(); - - il.Emit(OpCodes.Ldarg_0); - il.Emit(OpCodes.Ldarg_1); - il.Emit(OpCodes.Call, protectedMethod); - il.Emit(OpCodes.Ret); - - var interfaceMethod = AuthorizeAttributeType.GetMethod("IsAuthorized", BindingFlags.Public | BindingFlags.Instance); - builder.DefineMethodOverride(implementedMethod, interfaceMethod); - } - - /// - /// Creates the module builder. - /// - /// - /// A module builder represented as a instance - /// - private static ModuleBuilder CreateModuleBuilder() - { - const string name = "InheritedAuthorizeAttributes"; - - var assemblyName = new AssemblyName(name + "Assembly") - { - Version = typeof(AuthorizeAttributeBuilder).Assembly.GetName().Version - }; - - var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); - var moduleBuilder = assemblyBuilder.DefineDynamicModule(name + "Module"); - - return moduleBuilder; - } - } -} - diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/Security/IAuthorizeAttribute.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/Security/IAuthorizeAttribute.cs deleted file mode 100644 index bca5b8e9..00000000 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/Security/IAuthorizeAttribute.cs +++ /dev/null @@ -1,42 +0,0 @@ -// (c) Copyright Telerik Corp. -// This source is subject to the Microsoft Public License. -// See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL. -// All other rights reserved. - -using System.Web; - -namespace MvcSiteMapProvider.Security -{ - /// - /// IAuthorizeAttribute contract - /// - public interface IAuthorizeAttribute - { - /// - /// Gets or sets the order. - /// - /// The order. - int Order { get; set; } - - /// - /// Gets or sets the roles. - /// - /// The roles. - string Roles { get; set; } - - /// - /// Gets or sets the users. - /// - /// The users. - string Users { get; set; } - - /// - /// Determines whether the specified HTTP context is authorized. - /// - /// The HTTP context. - /// - /// true if the specified HTTP context is authorized; otherwise, false. - /// - bool IsAuthorized(HttpContextBase httpContext); - } -} diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/Security/IAuthorizeAttributeBuilder.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/Security/IAuthorizeAttributeBuilder.cs deleted file mode 100644 index e6eb22fe..00000000 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/Security/IAuthorizeAttributeBuilder.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Reflection; - -namespace MvcSiteMapProvider.Security -{ - /// - /// IAuthorizeAttributeBuilder interface - /// - public interface IAuthorizeAttributeBuilder - { - ConstructorInfo Build(Type parentType); - } -} diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/Security/InternalAuthorizeAttribute.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/Security/InternalAuthorizeAttribute.cs deleted file mode 100644 index e3bb9063..00000000 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/Security/InternalAuthorizeAttribute.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Web; -using System.Web.Mvc; - -namespace MvcSiteMapProvider.Security -{ - /// - /// InternalAuthorize class - /// - public class InternalAuthorizeAttribute - : AuthorizeAttribute, IAuthorizeAttribute - { - /// - /// Determines whether the specified HTTP context is authorized. - /// - /// The HTTP context. - /// - /// true if the specified HTTP context is authorized; otherwise, false. - /// - public bool IsAuthorized(HttpContextBase httpContext) - { - return AuthorizeCore(httpContext); - } - } -} diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/Web/Mvc/SiteMapHttpContext.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/Web/Mvc/SiteMapHttpContext.cs index d380ac14..6d1da8c6 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/Web/Mvc/SiteMapHttpContext.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/Web/Mvc/SiteMapHttpContext.cs @@ -5,7 +5,8 @@ namespace MvcSiteMapProvider.Web.Mvc /// /// HttpContext wrapper. /// - public class SiteMapHttpContext : HttpContextWrapper + public class SiteMapHttpContext + : HttpContextWrapper { private readonly HttpContext httpContext; private readonly ISiteMapNode node; @@ -28,13 +29,19 @@ public SiteMapHttpContext(HttpContext httpContext, ISiteMapNode node) /// /// Gets the object for the current HTTP request. /// - /// - /// - /// The current HTTP request. - /// + /// The current HTTP request. public override HttpRequestBase Request { get { return new SiteMapHttpRequest(this.httpContext.Request, this.node); } } + + /// + /// Gets the object for the current HTTP response. + /// + /// The current HTTP response. + public override HttpResponseBase Response + { + get { return new SiteMapHttpResponse(this.httpContext.Response); } + } } } \ No newline at end of file diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/Web/Mvc/SiteMapHttpResponse.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/Web/Mvc/SiteMapHttpResponse.cs new file mode 100644 index 00000000..a8880ef6 --- /dev/null +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/Web/Mvc/SiteMapHttpResponse.cs @@ -0,0 +1,22 @@ +using System; +using System.Web; + +namespace MvcSiteMapProvider.Web.Mvc +{ + /// + /// HttpResponse wrapper. + /// + public class SiteMapHttpResponse + : HttpResponseWrapper + { + public SiteMapHttpResponse(HttpResponse httpResponse) + : base(httpResponse) + { + } + + public override HttpCachePolicyBase Cache + { + get { return new SiteMapHttpResponseCache(); } + } + } +} diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/Web/Mvc/SiteMapHttpResponseCache.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/Web/Mvc/SiteMapHttpResponseCache.cs new file mode 100644 index 00000000..b14b726e --- /dev/null +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/Web/Mvc/SiteMapHttpResponseCache.cs @@ -0,0 +1,22 @@ +using System; +using System.Web; + +namespace MvcSiteMapProvider.Web.Mvc +{ + /// + /// HttpResponseCache wrapper. + /// + public class SiteMapHttpResponseCache + : HttpCachePolicyBase + { + public override void SetProxyMaxAge(TimeSpan delta) + { + // No implementation - skip this call when AuthorizeAttribute calls it + } + + public override void AddValidationCallback(HttpCacheValidateHandler handler, object data) + { + // No implementation - skip this call when AuthorizeAttribute calls it + } + } +}