From adffc95b8180d703646d15e2b2d177de68a22d2a Mon Sep 17 00:00:00 2001 From: Yishai Galatzer Date: Wed, 19 Mar 2014 20:01:40 -0700 Subject: [PATCH] AllowAnonymous attribute + Consumption + Sample --- .../MvcSample.Web/Filters/BlockAnonynous.cs | 19 +++++++++++++++++++ samples/MvcSample.Web/FiltersController.cs | 9 ++++++++- .../AuthorizationFilterContextExtensions.cs | 13 +++++++++++++ .../Filters/AllowAnonymousAttribute.cs | 5 +++-- .../Filters/AuthorizationFilterContext.cs | 18 ++++++++++-------- .../Filters/IAllowAnonymous.cs | 6 ++++++ .../ReflectedActionInvoker.cs | 5 +---- 7 files changed, 60 insertions(+), 15 deletions(-) create mode 100644 samples/MvcSample.Web/Filters/BlockAnonynous.cs create mode 100644 src/Microsoft.AspNet.Mvc.Core/Extensions/AuthorizationFilterContextExtensions.cs create mode 100644 src/Microsoft.AspNet.Mvc.Core/Filters/IAllowAnonymous.cs diff --git a/samples/MvcSample.Web/Filters/BlockAnonynous.cs b/samples/MvcSample.Web/Filters/BlockAnonynous.cs new file mode 100644 index 0000000000..1affbcffb7 --- /dev/null +++ b/samples/MvcSample.Web/Filters/BlockAnonynous.cs @@ -0,0 +1,19 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNet.Mvc; + +namespace MvcSample.Web.Filters +{ + public class BlockAnonynous : AuthorizationFilterAttribute + { + public override async Task Invoke(AuthorizationFilterContext context, Func next) + { + if (!context.HasAllowAnonymous()) + { + context.Fail(); + } + + await next(); + } + } +} \ No newline at end of file diff --git a/samples/MvcSample.Web/FiltersController.cs b/samples/MvcSample.Web/FiltersController.cs index afaf336f95..ccdf178415 100644 --- a/samples/MvcSample.Web/FiltersController.cs +++ b/samples/MvcSample.Web/FiltersController.cs @@ -9,6 +9,7 @@ namespace MvcSample.Web [PassThrough(Order = 0)] [PassThrough(Order = 2)] [InspectResultPage] + [BlockAnonynous] [UserNameProvider(Order = -1)] public class FiltersController : Controller { @@ -16,6 +17,7 @@ namespace MvcSample.Web // TODO: Add a real filter here [ServiceFilter(typeof(PassThroughAttribute))] + [AllowAnonymous] [AgeEnhancer] public IActionResult Index(int age, string userName) { @@ -28,5 +30,10 @@ namespace MvcSample.Web return View("MyView", _user); } - } + + public IActionResult Blocked(int age, string userName) + { + return Index(age, userName); + } + } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.Core/Extensions/AuthorizationFilterContextExtensions.cs b/src/Microsoft.AspNet.Mvc.Core/Extensions/AuthorizationFilterContextExtensions.cs new file mode 100644 index 0000000000..5828519569 --- /dev/null +++ b/src/Microsoft.AspNet.Mvc.Core/Extensions/AuthorizationFilterContextExtensions.cs @@ -0,0 +1,13 @@ +using System.Linq; +using Microsoft.AspNet.Mvc.Filters; + +namespace Microsoft.AspNet.Mvc +{ + public static class AuthorizationFilterContextExtensions + { + public static bool HasAllowAnonymous([NotNull] this AuthorizationFilterContext context) + { + return context.FilterItems.Any(item => item.Filter is IAllowAnonymous); + } + } +} diff --git a/src/Microsoft.AspNet.Mvc.Core/Filters/AllowAnonymousAttribute.cs b/src/Microsoft.AspNet.Mvc.Core/Filters/AllowAnonymousAttribute.cs index 8bf5f86c15..113819d498 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Filters/AllowAnonymousAttribute.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Filters/AllowAnonymousAttribute.cs @@ -1,9 +1,10 @@ using System; +using Microsoft.AspNet.Mvc.Filters; namespace Microsoft.AspNet.Mvc { - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] - public sealed class AllowAnonymousAttribute : Attribute + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + public class AllowAnonymousAttribute : Attribute, IAllowAnonymous { } } diff --git a/src/Microsoft.AspNet.Mvc.Core/Filters/AuthorizationFilterContext.cs b/src/Microsoft.AspNet.Mvc.Core/Filters/AuthorizationFilterContext.cs index afdce78c66..5dedb7f8d0 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Filters/AuthorizationFilterContext.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Filters/AuthorizationFilterContext.cs @@ -1,22 +1,24 @@ -namespace Microsoft.AspNet.Mvc +using System.Collections.Generic; + +namespace Microsoft.AspNet.Mvc { public class AuthorizationFilterContext { private IActionResult _actionResult; - private bool _fail; - public AuthorizationFilterContext(ActionContext actionContext) + public AuthorizationFilterContext([NotNull] ActionContext actionContext, [NotNull] IReadOnlyList filterItems) { ActionContext = actionContext; + FilterItems = filterItems; } - public bool HasFailed - { - get { return _fail; } - } + public bool HasFailed { get; private set; } public ActionContext ActionContext { get; private set; } + public IReadOnlyList FilterItems { get; private set; } + + // Result public IActionResult ActionResult { get { return _actionResult; } @@ -33,7 +35,7 @@ public void Fail() { - _fail = true; + HasFailed = true; } } } diff --git a/src/Microsoft.AspNet.Mvc.Core/Filters/IAllowAnonymous.cs b/src/Microsoft.AspNet.Mvc.Core/Filters/IAllowAnonymous.cs new file mode 100644 index 0000000000..36f4bcf461 --- /dev/null +++ b/src/Microsoft.AspNet.Mvc.Core/Filters/IAllowAnonymous.cs @@ -0,0 +1,6 @@ +namespace Microsoft.AspNet.Mvc.Filters +{ + public interface IAllowAnonymous : IFilter + { + } +} diff --git a/src/Microsoft.AspNet.Mvc.Core/ReflectedActionInvoker.cs b/src/Microsoft.AspNet.Mvc.Core/ReflectedActionInvoker.cs index b718bf1fd3..fa825b98cc 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ReflectedActionInvoker.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ReflectedActionInvoker.cs @@ -48,7 +48,6 @@ namespace Microsoft.AspNet.Mvc _filterProvider.Invoke(filterProviderContext); - // TODO: arrange when needed. PreArrangeFiltersInPipeline(filterProviderContext); var modelState = new ModelStateDictionary(); @@ -73,7 +72,7 @@ namespace Microsoft.AspNet.Mvc var authZEndPoint = new AuthorizationFilterEndPoint(); _authorizationFilters.Add(authZEndPoint); - var authZContext = new AuthorizationFilterContext(_actionContext); + var authZContext = new AuthorizationFilterContext(_actionContext, filterProviderContext.Result.ToArray()); var authZPipeline = new FilterPipelineBuilder(_authorizationFilters, authZContext); await authZPipeline.InvokeAsync(); @@ -173,8 +172,6 @@ namespace Microsoft.AspNet.Mvc var actionFilter = filter as IActionFilter; var actionResultFilter = filter as IActionResultFilter; - // TODO: Exception filters - if (authFilter != null) { _authorizationFilters.Add(authFilter);