Skip to content

Commit

Permalink
Fixes #156, fixes #220, custom AuthorizeAttribute implementations tha…
Browse files Browse the repository at this point in the history
…t are sealed or do not have a public default constructor fail to authorize.
  • Loading branch information
NightOwl888 committed Aug 30, 2013
1 parent 051a581 commit 272f33c
Show file tree
Hide file tree
Showing 13 changed files with 68 additions and 367 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,6 @@ public static void SetUp(Container container)
<IBuildManager>()));

// Configure Security
container.RegisterSingle<AuthorizeAttributeAclModule>(() => new AuthorizeAttributeAclModule(
container.GetInstance<IMvcContextFactory>(),
container.GetInstance<IObjectCopier>(),
container.GetInstance<IControllerDescriptorFactory>(),
container.GetInstance<IControllerBuilder>(),
container.GetInstance<IAuthorizeAttributeBuilder>(),
container.GetInstance<IGlobalFilterProvider>()));

container.RegisterAll<IAclModule>(typeof(AuthorizeAttributeAclModule), typeof(XmlRolesAclModule));
container.RegisterSingle<IAclModule>(() => new CompositeAclModule(container.GetAllInstances<IAclModule>().ToArray()));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,13 @@
<Compile Include="Reflection\PluginInstantiator.cs" />
<Compile Include="DI\SiteMapFactoryContainer.cs" />
<Compile Include="DI\SiteMapNodeFactoryContainer.cs" />
<Compile Include="Security\IAuthorizeAttributeBuilder.cs" />
<Compile Include="TrimEmptyGroupingNodesVisibilityProvider.cs" />
<Compile Include="Web\Mvc\ControllerExtensions.cs" />
<Compile Include="Web\Mvc\Filters\Filter.cs" />
<Compile Include="Web\Mvc\Filters\GlobalFilterProvider.cs" />
<Compile Include="Web\Mvc\Filters\IGlobalFilterProvider.cs" />
<Compile Include="Web\Mvc\SiteMapHttpResponse.cs" />
<Compile Include="Web\Mvc\SiteMapHttpResponseCache.cs" />
<Compile Include="Web\SiteMapNodeExtensions.cs" />
<Compile Include="Xml\ISiteMapXmlReservedAttributeNameProvider.cs" />
<Compile Include="Xml\SiteMapXmlReservedAttributeNameProvider.cs" />
Expand All @@ -174,7 +175,6 @@
<Compile Include="Loader\SiteMapCreator.cs" />
<Compile Include="Loader\SiteMapLoader.cs" />
<Compile Include="Collections\Specialized\PreservedRouteParameterCollection.cs" />
<Compile Include="Reflection\IObjectCopier.cs" />
<Compile Include="Collections\Specialized\IMetaRobotsValueCollection.cs" />
<Compile Include="Collections\Specialized\MetaRobotsValueCollection.cs" />
<Compile Include="Collections\Specialized\RoleCollection.cs" />
Expand Down Expand Up @@ -242,12 +242,8 @@
</Compile>
<Compile Include="Security\AclModuleNotSupportedException.cs" />
<Compile Include="Security\AuthorizeAttributeAclModule.cs" />
<Compile Include="Security\AuthorizeAttributeBuilder.cs" />
<Compile Include="Security\CompositeAclModule.cs" />
<Compile Include="Security\IAclModule.cs" />
<Compile Include="Security\IAuthorizeAttribute.cs" />
<Compile Include="Security\InternalAuthorizeAttribute.cs" />
<Compile Include="Reflection\ObjectCopier.cs" />
<Compile Include="Security\XmlRolesAclModule.cs" />
<Compile Include="Builder\IMvcSiteMapNodeAttributeDefinition.cs" />
<Compile Include="Builder\INodeKeyGenerator.cs" />
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,54 +7,41 @@
using System.Web.Routing;
using MvcSiteMapProvider.Web.Mvc;
using MvcSiteMapProvider.Web.Mvc.Filters;
using MvcSiteMapProvider.Reflection;

namespace MvcSiteMapProvider.Security
{
/// <summary>
/// AuthorizeAttributeAclModule class
/// An ACL module that determines whether the current user has access to a given node based on the MVC AuthorizeAttribute.
/// </summary>
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

Expand Down Expand Up @@ -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<AuthorizeAttribute> authorizeAttributes, ControllerContext controllerContext)
protected virtual bool VerifyAuthorizeAttributes(IEnumerable<AuthorizeAttribute> 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;
}
Expand Down Expand Up @@ -221,53 +203,13 @@ protected virtual IEnumerable<AuthorizeAttribute> 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)
Expand Down
Loading

0 comments on commit 272f33c

Please sign in to comment.