React to Authorize changes

This commit is contained in:
Hao Kung 2015-02-16 15:40:57 -08:00
parent 3d30fd653e
commit 94ef6cf8fa
24 changed files with 524 additions and 368 deletions

View File

@ -3,6 +3,7 @@
using System; using System;
using Microsoft.AspNet.Mvc; using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Security;
using MvcSample.Web.Filters; using MvcSample.Web.Filters;
using MvcSample.Web.Models; using MvcSample.Web.Models;
@ -50,14 +51,12 @@ namespace MvcSample.Web
return new ChallengeResult(); return new ChallengeResult();
} }
[Authorize("CanViewPage")]
public ActionResult NotGrantedClaim(int age = 20, string userName = "SampleUser") public ActionResult NotGrantedClaim(int age = 20, string userName = "SampleUser")
{ {
return Index(age, userName); return Index(age, userName);
} }
[FakeUser] [FakeUser]
[Authorize("CanViewAnything")]
public ActionResult AllGranted(int age = 20, string userName = "SampleUser") public ActionResult AllGranted(int age = 20, string userName = "SampleUser")
{ {
return Index(age, userName); return Index(age, userName);

View File

@ -40,19 +40,6 @@ namespace MvcSample.Web
app.UseServices(services => app.UseServices(services =>
{ {
services.ConfigureAuthorization(auth =>
{
auth.AddPolicy("CanViewPage",
new AuthorizationPolicyBuilder()
.RequiresClaim("Permission", "CanViewPage", "CanViewAnything").Build());
auth.AddPolicy("CanViewAnything",
new AuthorizationPolicyBuilder()
.RequiresClaim("Permission", "CanViewAnything").Build());
// This policy basically requires that the auth type is present
var basicPolicy = new AuthorizationPolicyBuilder("Basic").RequiresClaim(ClaimTypes.NameIdentifier);
auth.AddPolicy("RequireBasic", basicPolicy.Build());
});
services.AddMvc(); services.AddMvc();
services.AddSingleton<PassThroughAttribute>(); services.AddSingleton<PassThroughAttribute>();
services.AddSingleton<UserNameService>(); services.AddSingleton<UserNameService>();
@ -131,4 +118,4 @@ namespace MvcSample.Web
}); });
} }
} }
} }

View File

@ -8,6 +8,8 @@ using System.Reflection;
using Microsoft.AspNet.Mvc.Description; using Microsoft.AspNet.Mvc.Description;
using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Routing; using Microsoft.AspNet.Mvc.Routing;
using Microsoft.AspNet.Security;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Mvc.ApplicationModels namespace Microsoft.AspNet.Mvc.ApplicationModels
{ {
@ -16,6 +18,13 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
/// </summary> /// </summary>
public class DefaultActionModelBuilder : IActionModelBuilder public class DefaultActionModelBuilder : IActionModelBuilder
{ {
private readonly AuthorizationOptions _authorizationOptions;
public DefaultActionModelBuilder(IOptions<AuthorizationOptions> options)
{
_authorizationOptions = options?.Options ?? new AuthorizationOptions();
}
/// <inheritdoc /> /// <inheritdoc />
public IEnumerable<ActionModel> BuildActionModels([NotNull] TypeInfo typeInfo, [NotNull] MethodInfo methodInfo) public IEnumerable<ActionModel> BuildActionModels([NotNull] TypeInfo typeInfo, [NotNull] MethodInfo methodInfo)
{ {
@ -256,6 +265,12 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
AddRange(actionModel.ActionConstraints, attributes.OfType<IActionConstraintMetadata>()); AddRange(actionModel.ActionConstraints, attributes.OfType<IActionConstraintMetadata>());
AddRange(actionModel.Filters, attributes.OfType<IFilter>()); AddRange(actionModel.Filters, attributes.OfType<IFilter>());
var policy = AuthorizationPolicy.Combine(_authorizationOptions, attributes.OfType<AuthorizeAttribute>());
if (policy != null)
{
actionModel.Filters.Add(new AuthorizeFilter(policy));
}
var actionName = attributes.OfType<ActionNameAttribute>().FirstOrDefault(); var actionName = attributes.OfType<ActionNameAttribute>().FirstOrDefault();
if (actionName?.Name != null) if (actionName?.Name != null)
{ {

View File

@ -8,7 +8,9 @@ using System.Reflection;
using Microsoft.AspNet.Mvc.Description; using Microsoft.AspNet.Mvc.Description;
using Microsoft.AspNet.Mvc.Filters; using Microsoft.AspNet.Mvc.Filters;
using Microsoft.AspNet.Mvc.Routing; using Microsoft.AspNet.Mvc.Routing;
using Microsoft.AspNet.Security;
using Microsoft.Framework.Logging; using Microsoft.Framework.Logging;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Mvc.ApplicationModels namespace Microsoft.AspNet.Mvc.ApplicationModels
{ {
@ -19,15 +21,20 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
{ {
private readonly IActionModelBuilder _actionModelBuilder; private readonly IActionModelBuilder _actionModelBuilder;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly AuthorizationOptions _authorizationOptions;
/// <summary> /// <summary>
/// Creates a new <see cref="DefaultControllerModelBuilder"/>. /// Creates a new <see cref="DefaultControllerModelBuilder"/>.
/// </summary> /// </summary>
/// <param name="actionModelBuilder">The <see cref="IActionModelBuilder"/> used to create actions.</param> /// <param name="actionModelBuilder">The <see cref="IActionModelBuilder"/> used to create actions.</param>
public DefaultControllerModelBuilder(IActionModelBuilder actionModelBuilder, ILoggerFactory loggerFactory) public DefaultControllerModelBuilder(
IActionModelBuilder actionModelBuilder,
ILoggerFactory loggerFactory,
IOptions<AuthorizationOptions> options)
{ {
_actionModelBuilder = actionModelBuilder; _actionModelBuilder = actionModelBuilder;
_logger = loggerFactory.Create<DefaultControllerModelBuilder>(); _logger = loggerFactory.Create<DefaultControllerModelBuilder>();
_authorizationOptions = options?.Options ?? new AuthorizationOptions();
} }
/// <inheritdoc /> /// <inheritdoc />
@ -72,6 +79,12 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
AddRange(controllerModel.Filters, attributes.OfType<IFilter>()); AddRange(controllerModel.Filters, attributes.OfType<IFilter>());
AddRange(controllerModel.RouteConstraints, attributes.OfType<IRouteConstraintProvider>()); AddRange(controllerModel.RouteConstraints, attributes.OfType<IRouteConstraintProvider>());
var policy = AuthorizationPolicy.Combine(_authorizationOptions, attributes.OfType<AuthorizeAttribute>());
if (policy != null)
{
controllerModel.Filters.Add(new AuthorizeFilter(policy));
}
AddRange( AddRange(
controllerModel.AttributeRoutes, controllerModel.AttributeRoutes,
attributes.OfType<IRouteTemplateProvider>().Select(rtp => new AttributeRouteModel(rtp))); attributes.OfType<IRouteTemplateProvider>().Select(rtp => new AttributeRouteModel(rtp)));

View File

@ -1,88 +0,0 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.Core;
using Microsoft.AspNet.Security;
using Microsoft.Framework.DependencyInjection;
namespace Microsoft.AspNet.Mvc
{
public class AuthorizeAttribute : AuthorizationFilterAttribute
{
private string _roles;
private string[] _rolesSplit;
public AuthorizeAttribute() { }
public AuthorizeAttribute(string policy)
{
Policy = policy;
}
public string Policy { get; set; }
public string Roles
{
get { return _roles; }
set
{
_roles = value;
if (string.IsNullOrWhiteSpace(_roles))
{
_rolesSplit = null;
}
else
{
_rolesSplit = _roles.Split(',');
}
}
}
public override async Task OnAuthorizationAsync([NotNull] AuthorizationContext context)
{
var httpContext = context.HttpContext;
// Allow Anonymous skips all authorization
if (HasAllowAnonymous(context))
{
return;
}
var authService = httpContext.RequestServices.GetRequiredService<IAuthorizationService>();
// Build a policy for the requested roles if specified
if (_rolesSplit != null)
{
var rolesPolicy = new AuthorizationPolicyBuilder();
rolesPolicy.RequiresRole(_rolesSplit);
if (!await authService.AuthorizeAsync(rolesPolicy.Build(), httpContext, context))
{
Fail(context);
return;
}
}
var authorized = (Policy == null)
// [Authorize] with no policy just requires any authenticated user
? await authService.AuthorizeAsync(BuildAnyAuthorizedUserPolicy(), httpContext, context)
: await authService.AuthorizeAsync(Policy, httpContext, context);
if (!authorized)
{
Fail(context);
}
}
private static AuthorizationPolicy BuildAnyAuthorizedUserPolicy()
{
return new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
}
public sealed override void OnAuthorization([NotNull] AuthorizationContext context)
{
// The async filter will be called by the filter pipeline.
throw new NotImplementedException(Resources.AuthorizeAttribute_OnAuthorizationNotImplemented);
}
}
}

View File

@ -0,0 +1,62 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Security;
using Microsoft.Framework.DependencyInjection;
namespace Microsoft.AspNet.Mvc
{
/// <summary>
/// An implementation of <see cref="IAsyncAuthorizationFilter"/>
/// </summary>
public class AuthorizeFilter : IAsyncAuthorizationFilter
{
/// <summary>
/// Authorize filter for a specific policy.
/// </summary>
/// <param name="policy"></param>
public AuthorizeFilter([NotNull] AuthorizationPolicy policy)
{
Policy = policy;
}
/// <summary>
/// Authorization policy to be used.
/// </summary>
public AuthorizationPolicy Policy { get; private set; }
/// <inheritdoc />
public virtual async Task OnAuthorizationAsync([NotNull] AuthorizationContext context)
{
// Build a ClaimsPrincipal with the Policy's required authentication types
if (Policy.ActiveAuthenticationTypes != null && Policy.ActiveAuthenticationTypes.Any())
{
var results = await context.HttpContext.AuthenticateAsync(Policy.ActiveAuthenticationTypes);
if (results != null)
{
context.HttpContext.User = new ClaimsPrincipal(results.Where(r => r.Identity != null).Select(r => r.Identity));
}
}
// Allow Anonymous skips all authorization
if (context.Filters.Any(item => item is IAllowAnonymous))
{
return;
}
var httpContext = context.HttpContext;
var authService = httpContext.RequestServices.GetRequiredService<IAuthorizationService>();
// Note: Default Anonymous User is new ClaimsPrincipal(new ClaimsIdentity())
if (httpContext.User == null ||
!httpContext.User.Identities.Any(i => i.IsAuthenticated) ||
!await authService.AuthorizeAsync(httpContext.User, context, Policy))
{
context.Result = new ChallengeResult(Policy.ActiveAuthenticationTypes.ToArray());
}
}
}
}

View File

@ -4,6 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using Microsoft.AspNet.Security;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Mvc.ApplicationModels namespace Microsoft.AspNet.Mvc.ApplicationModels
@ -43,14 +44,14 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
{ {
// Arrange // Arrange
var action = new ActionModel(typeof(TestController).GetMethod("Edit"), var action = new ActionModel(typeof(TestController).GetMethod("Edit"),
new List<object>() { new HttpGetAttribute() }); new List<object>() { new HttpGetAttribute(), new AuthorizeAttribute() });
action.ActionConstraints.Add(new HttpMethodConstraint(new string[] { "GET" })); action.ActionConstraints.Add(new HttpMethodConstraint(new string[] { "GET" }));
action.ActionName = "Edit"; action.ActionName = "Edit";
action.Controller = new ControllerModel(typeof(TestController).GetTypeInfo(), action.Controller = new ControllerModel(typeof(TestController).GetTypeInfo(),
new List<object>()); new List<object>());
action.Filters.Add(new AuthorizeAttribute()); action.Filters.Add(new AuthorizeFilter(new AuthorizationPolicyBuilder().Build()));
action.HttpMethods.Add("GET"); action.HttpMethods.Add("GET");
action.RouteConstraints.Add(new AreaAttribute("Admin")); action.RouteConstraints.Add(new AreaAttribute("Admin"));
action.Properties.Add(new KeyValuePair<object, object>("test key", "test value")); action.Properties.Add(new KeyValuePair<object, object>("test key", "test value"));

View File

@ -4,6 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using Microsoft.AspNet.Security;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Mvc.ApplicationModels namespace Microsoft.AspNet.Mvc.ApplicationModels
@ -49,12 +50,12 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
{ {
// Arrange // Arrange
var controller = new ControllerModel(typeof(TestController).GetTypeInfo(), var controller = new ControllerModel(typeof(TestController).GetTypeInfo(),
new List<object>() { new HttpGetAttribute() }); new List<object>() { new HttpGetAttribute(), new AuthorizeAttribute() });
controller.ActionConstraints.Add(new HttpMethodConstraint(new string[] { "GET" })); controller.ActionConstraints.Add(new HttpMethodConstraint(new string[] { "GET" }));
controller.Application = new ApplicationModel(); controller.Application = new ApplicationModel();
controller.ControllerName = "cool"; controller.ControllerName = "cool";
controller.Filters.Add(new AuthorizeAttribute()); controller.Filters.Add(new AuthorizeFilter(new AuthorizationPolicyBuilder().Build()));
controller.RouteConstraints.Add(new AreaAttribute("Admin")); controller.RouteConstraints.Add(new AreaAttribute("Admin"));
controller.Properties.Add(new KeyValuePair<object, object>("test key", "test value")); controller.Properties.Add(new KeyValuePair<object, object>("test key", "test value"));

View File

@ -5,6 +5,9 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using Microsoft.AspNet.Security;
using Microsoft.Framework.OptionsModel;
using Moq;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Mvc.ApplicationModels namespace Microsoft.AspNet.Mvc.ApplicationModels
@ -18,7 +21,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void IsAction_WithInheritedMethods(string methodName, bool expected) public void IsAction_WithInheritedMethods(string methodName, bool expected)
{ {
// Arrange // Arrange
var builder = new AccessibleActionModelBuilder(); var builder = CreateTestAccessibleActionModelBuilder();
var method = typeof(DerivedController).GetMethod(methodName); var method = typeof(DerivedController).GetMethod(methodName);
Assert.NotNull(method); Assert.NotNull(method);
@ -33,7 +36,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void IsAction_OverridenMethodControllerClass() public void IsAction_OverridenMethodControllerClass()
{ {
// Arrange // Arrange
var builder = new AccessibleActionModelBuilder(); var builder = CreateTestAccessibleActionModelBuilder();
var method = typeof(BaseController).GetMethod(nameof(BaseController.Redirect)); var method = typeof(BaseController).GetMethod(nameof(BaseController.Redirect));
Assert.NotNull(method); Assert.NotNull(method);
@ -48,7 +51,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void IsAction_PrivateMethod_FromUserDefinedController() public void IsAction_PrivateMethod_FromUserDefinedController()
{ {
// Arrange // Arrange
var builder = new AccessibleActionModelBuilder(); var builder = CreateTestAccessibleActionModelBuilder();
var method = typeof(DerivedController).GetMethod( var method = typeof(DerivedController).GetMethod(
"PrivateMethod", "PrivateMethod",
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
@ -65,7 +68,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void IsAction_OperatorOverloadingMethod_FromOperatorOverloadingController() public void IsAction_OperatorOverloadingMethod_FromOperatorOverloadingController()
{ {
// Arrange // Arrange
var builder = new AccessibleActionModelBuilder(); var builder = CreateTestAccessibleActionModelBuilder();
var method = typeof(OperatorOverloadingController).GetMethod("op_Addition"); var method = typeof(OperatorOverloadingController).GetMethod("op_Addition");
Assert.NotNull(method); Assert.NotNull(method);
Assert.True(method.IsSpecialName); Assert.True(method.IsSpecialName);
@ -81,7 +84,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void IsAction_GenericMethod_FromUserDefinedController() public void IsAction_GenericMethod_FromUserDefinedController()
{ {
// Arrange // Arrange
var builder = new AccessibleActionModelBuilder(); var builder = CreateTestAccessibleActionModelBuilder();
var method = typeof(DerivedController).GetMethod("GenericMethod"); var method = typeof(DerivedController).GetMethod("GenericMethod");
Assert.NotNull(method); Assert.NotNull(method);
@ -96,7 +99,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void IsAction_OverridenNonActionMethod() public void IsAction_OverridenNonActionMethod()
{ {
// Arrange // Arrange
var builder = new AccessibleActionModelBuilder(); var builder = CreateTestAccessibleActionModelBuilder();
var method = typeof(DerivedController).GetMethod("OverridenNonActionMethod"); var method = typeof(DerivedController).GetMethod("OverridenNonActionMethod");
Assert.NotNull(method); Assert.NotNull(method);
@ -115,7 +118,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void IsAction_OverriddenMethodsFromObjectClass(string methodName) public void IsAction_OverriddenMethodsFromObjectClass(string methodName)
{ {
// Arrange // Arrange
var builder = new AccessibleActionModelBuilder(); var builder = CreateTestAccessibleActionModelBuilder();
var method = typeof(DerivedController).GetMethod( var method = typeof(DerivedController).GetMethod(
methodName, methodName,
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
@ -132,7 +135,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void IsAction_DerivedControllerIDisposableDisposeMethod() public void IsAction_DerivedControllerIDisposableDisposeMethod()
{ {
// Arrange // Arrange
var builder = new AccessibleActionModelBuilder(); var builder = CreateTestAccessibleActionModelBuilder();
var typeInfo = typeof(DerivedController).GetTypeInfo(); var typeInfo = typeof(DerivedController).GetTypeInfo();
var methodInfo = var methodInfo =
typeInfo.GetRuntimeInterfaceMap(typeof(IDisposable)).TargetMethods[0]; typeInfo.GetRuntimeInterfaceMap(typeof(IDisposable)).TargetMethods[0];
@ -150,7 +153,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void IsAction_DerivedControllerDisposeMethod() public void IsAction_DerivedControllerDisposeMethod()
{ {
// Arrange // Arrange
var builder = new AccessibleActionModelBuilder(); var builder = CreateTestAccessibleActionModelBuilder();
var typeInfo = typeof(DerivedController).GetTypeInfo(); var typeInfo = typeof(DerivedController).GetTypeInfo();
var methodInfo = var methodInfo =
typeInfo.GetRuntimeInterfaceMap(typeof(IDisposable)).TargetMethods[0]; typeInfo.GetRuntimeInterfaceMap(typeof(IDisposable)).TargetMethods[0];
@ -172,7 +175,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void IsAction_OverriddenDisposeMethod() public void IsAction_OverriddenDisposeMethod()
{ {
// Arrange // Arrange
var builder = new AccessibleActionModelBuilder(); var builder = CreateTestAccessibleActionModelBuilder();
var typeInfo = typeof(DerivedOverriddenDisposeController).GetTypeInfo(); var typeInfo = typeof(DerivedOverriddenDisposeController).GetTypeInfo();
var method = typeInfo.GetDeclaredMethods("Dispose").SingleOrDefault(); var method = typeInfo.GetDeclaredMethods("Dispose").SingleOrDefault();
Assert.NotNull(method); Assert.NotNull(method);
@ -188,7 +191,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void IsAction_NewDisposeMethod() public void IsAction_NewDisposeMethod()
{ {
// Arrange // Arrange
var builder = new AccessibleActionModelBuilder(); var builder = CreateTestAccessibleActionModelBuilder();
var typeInfo = typeof(DerivedNewDisposeController).GetTypeInfo(); var typeInfo = typeof(DerivedNewDisposeController).GetTypeInfo();
var method = typeInfo.GetDeclaredMethods("Dispose").SingleOrDefault(); var method = typeInfo.GetDeclaredMethods("Dispose").SingleOrDefault();
Assert.NotNull(method); Assert.NotNull(method);
@ -204,7 +207,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void IsAction_PocoControllerIDisposableDisposeMethod() public void IsAction_PocoControllerIDisposableDisposeMethod()
{ {
// Arrange // Arrange
var builder = new AccessibleActionModelBuilder(); var builder = CreateTestAccessibleActionModelBuilder();
var typeInfo = typeof(IDisposablePocoController).GetTypeInfo(); var typeInfo = typeof(IDisposablePocoController).GetTypeInfo();
var methodInfo = var methodInfo =
typeInfo.GetRuntimeInterfaceMap(typeof(IDisposable)).TargetMethods[0]; typeInfo.GetRuntimeInterfaceMap(typeof(IDisposable)).TargetMethods[0];
@ -222,7 +225,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void IsAction_PocoControllerDisposeMethod() public void IsAction_PocoControllerDisposeMethod()
{ {
// Arrange // Arrange
var builder = new AccessibleActionModelBuilder(); var builder = CreateTestAccessibleActionModelBuilder();
var typeInfo = typeof(IDisposablePocoController).GetTypeInfo(); var typeInfo = typeof(IDisposablePocoController).GetTypeInfo();
var methodInfo = var methodInfo =
typeInfo.GetRuntimeInterfaceMap(typeof(IDisposable)).TargetMethods[0]; typeInfo.GetRuntimeInterfaceMap(typeof(IDisposable)).TargetMethods[0];
@ -244,7 +247,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void IsAction_SimplePocoControllerDisposeMethod() public void IsAction_SimplePocoControllerDisposeMethod()
{ {
// Arrange // Arrange
var builder = new AccessibleActionModelBuilder(); var builder = CreateTestAccessibleActionModelBuilder();
var typeInfo = typeof(SimplePocoController).GetTypeInfo(); var typeInfo = typeof(SimplePocoController).GetTypeInfo();
var methods = typeInfo.GetMethods().Where(m => m.Name.Equals("Dispose")); var methods = typeInfo.GetMethods().Where(m => m.Name.Equals("Dispose"));
@ -267,7 +270,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void IsAction_StaticMethods(string methodName) public void IsAction_StaticMethods(string methodName)
{ {
// Arrange // Arrange
var builder = new AccessibleActionModelBuilder(); var builder = CreateTestAccessibleActionModelBuilder();
var method = typeof(DerivedController).GetMethod( var method = typeof(DerivedController).GetMethod(
methodName, methodName,
BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
@ -284,7 +287,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void GetActions_ConventionallyRoutedAction_WithoutHttpConstraints() public void GetActions_ConventionallyRoutedAction_WithoutHttpConstraints()
{ {
// Arrange // Arrange
var builder = new DefaultActionModelBuilder(); var builder = CreateTestDefaultActionModelBuilder();
var typeInfo = typeof(ConventionallyRoutedController).GetTypeInfo(); var typeInfo = typeof(ConventionallyRoutedController).GetTypeInfo();
var actionName = nameof(ConventionallyRoutedController.Edit); var actionName = nameof(ConventionallyRoutedController.Edit);
@ -303,7 +306,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void GetActions_ConventionallyRoutedAction_WithHttpConstraints() public void GetActions_ConventionallyRoutedAction_WithHttpConstraints()
{ {
// Arrange // Arrange
var builder = new DefaultActionModelBuilder(); var builder = CreateTestDefaultActionModelBuilder();
var typeInfo = typeof(ConventionallyRoutedController).GetTypeInfo(); var typeInfo = typeof(ConventionallyRoutedController).GetTypeInfo();
var actionName = nameof(ConventionallyRoutedController.Update); var actionName = nameof(ConventionallyRoutedController.Update);
@ -320,11 +323,34 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
Assert.IsType<CustomHttpMethodsAttribute>(Assert.Single(action.Attributes)); Assert.IsType<CustomHttpMethodsAttribute>(Assert.Single(action.Attributes));
} }
[Fact]
public void GetActions_BaseAuthorizeFiltersAreStillValidWhenOverriden()
{
// Arrange
var options = new AuthorizationOptions();
options.AddPolicy("Base", policy => policy.RequiresClaim("Basic").RequiresClaim("Basic2"));
options.AddPolicy("Derived", policy => policy.RequiresClaim("Derived"));
var builder = CreateTestDefaultActionModelBuilder(options);
var typeInfo = typeof(DerivedController).GetTypeInfo();
var actionName = nameof(DerivedController.Authorize);
// Act
var actions = builder.BuildActionModels(typeInfo, typeInfo.GetMethod(actionName));
// Assert
var action = Assert.Single(actions);
Assert.Equal("Authorize", action.ActionName);
Assert.Null(action.AttributeRouteModel);
var authorizeFilters = action.Filters.OfType<AuthorizeFilter>();
Assert.Single(authorizeFilters);
Assert.Equal(3, authorizeFilters.First().Policy.Requirements.Count);
}
[Fact] [Fact]
public void GetActions_ConventionallyRoutedActionWithHttpConstraints_AndInvalidRouteTemplateProvider() public void GetActions_ConventionallyRoutedActionWithHttpConstraints_AndInvalidRouteTemplateProvider()
{ {
// Arrange // Arrange
var builder = new DefaultActionModelBuilder(); var builder = CreateTestDefaultActionModelBuilder();
var typeInfo = typeof(ConventionallyRoutedController).GetTypeInfo(); var typeInfo = typeof(ConventionallyRoutedController).GetTypeInfo();
var actionName = nameof(ConventionallyRoutedController.Delete); var actionName = nameof(ConventionallyRoutedController.Delete);
@ -346,7 +372,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void GetActions_ConventionallyRoutedAction_WithMultipleHttpConstraints() public void GetActions_ConventionallyRoutedAction_WithMultipleHttpConstraints()
{ {
// Arrange // Arrange
var builder = new DefaultActionModelBuilder(); var builder = CreateTestDefaultActionModelBuilder();
var typeInfo = typeof(ConventionallyRoutedController).GetTypeInfo(); var typeInfo = typeof(ConventionallyRoutedController).GetTypeInfo();
var actionName = nameof(ConventionallyRoutedController.Details); var actionName = nameof(ConventionallyRoutedController.Details);
@ -365,7 +391,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void GetActions_ConventionallyRoutedAction_WithMultipleOverlappingHttpConstraints() public void GetActions_ConventionallyRoutedAction_WithMultipleOverlappingHttpConstraints()
{ {
// Arrange // Arrange
var builder = new DefaultActionModelBuilder(); var builder = CreateTestDefaultActionModelBuilder();
var typeInfo = typeof(ConventionallyRoutedController).GetTypeInfo(); var typeInfo = typeof(ConventionallyRoutedController).GetTypeInfo();
var actionName = nameof(ConventionallyRoutedController.List); var actionName = nameof(ConventionallyRoutedController.List);
@ -385,7 +411,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void GetActions_AttributeRouteOnAction() public void GetActions_AttributeRouteOnAction()
{ {
// Arrange // Arrange
var builder = new DefaultActionModelBuilder(); var builder = CreateTestDefaultActionModelBuilder();
var typeInfo = typeof(NoRouteAttributeOnControllerController).GetTypeInfo(); var typeInfo = typeof(NoRouteAttributeOnControllerController).GetTypeInfo();
var actionName = nameof(NoRouteAttributeOnControllerController.Edit); var actionName = nameof(NoRouteAttributeOnControllerController.Edit);
@ -410,7 +436,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void GetActions_AttributeRouteOnAction_RouteAttribute() public void GetActions_AttributeRouteOnAction_RouteAttribute()
{ {
// Arrange // Arrange
var builder = new DefaultActionModelBuilder(); var builder = CreateTestDefaultActionModelBuilder();
var typeInfo = typeof(NoRouteAttributeOnControllerController).GetTypeInfo(); var typeInfo = typeof(NoRouteAttributeOnControllerController).GetTypeInfo();
var actionName = nameof(NoRouteAttributeOnControllerController.Update); var actionName = nameof(NoRouteAttributeOnControllerController.Update);
@ -434,7 +460,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void GetActions_AttributeRouteOnAction_AcceptVerbsAttributeWithTemplate() public void GetActions_AttributeRouteOnAction_AcceptVerbsAttributeWithTemplate()
{ {
// Arrange // Arrange
var builder = new DefaultActionModelBuilder(); var builder = CreateTestDefaultActionModelBuilder();
var typeInfo = typeof(NoRouteAttributeOnControllerController).GetTypeInfo(); var typeInfo = typeof(NoRouteAttributeOnControllerController).GetTypeInfo();
var actionName = nameof(NoRouteAttributeOnControllerController.List); var actionName = nameof(NoRouteAttributeOnControllerController.List);
@ -458,7 +484,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void GetActions_AttributeRouteOnAction_CreatesOneActionInforPerRouteTemplate() public void GetActions_AttributeRouteOnAction_CreatesOneActionInforPerRouteTemplate()
{ {
// Arrange // Arrange
var builder = new DefaultActionModelBuilder(); var builder = CreateTestDefaultActionModelBuilder();
var typeInfo = typeof(NoRouteAttributeOnControllerController).GetTypeInfo(); var typeInfo = typeof(NoRouteAttributeOnControllerController).GetTypeInfo();
var actionName = nameof(NoRouteAttributeOnControllerController.Index); var actionName = nameof(NoRouteAttributeOnControllerController.Index);
@ -489,7 +515,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void GetActions_NoRouteOnController_AllowsConventionallyRoutedActions_OnTheSameController() public void GetActions_NoRouteOnController_AllowsConventionallyRoutedActions_OnTheSameController()
{ {
// Arrange // Arrange
var builder = new DefaultActionModelBuilder(); var builder = CreateTestDefaultActionModelBuilder();
var typeInfo = typeof(NoRouteAttributeOnControllerController).GetTypeInfo(); var typeInfo = typeof(NoRouteAttributeOnControllerController).GetTypeInfo();
var actionName = nameof(NoRouteAttributeOnControllerController.Remove); var actionName = nameof(NoRouteAttributeOnControllerController.Remove);
@ -514,7 +540,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void GetActions_RouteAttributeOnController_CreatesAttributeRoute_ForNonAttributedActions(Type controller) public void GetActions_RouteAttributeOnController_CreatesAttributeRoute_ForNonAttributedActions(Type controller)
{ {
// Arrange // Arrange
var builder = new DefaultActionModelBuilder(); var builder = CreateTestDefaultActionModelBuilder();
var typeInfo = controller.GetTypeInfo(); var typeInfo = controller.GetTypeInfo();
// Act // Act
@ -538,7 +564,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void GetActions_RouteOnController_CreatesOneActionInforPerRouteTemplateOnAction(Type controller) public void GetActions_RouteOnController_CreatesOneActionInforPerRouteTemplateOnAction(Type controller)
{ {
// Arrange // Arrange
var builder = new DefaultActionModelBuilder(); var builder = CreateTestDefaultActionModelBuilder();
var typeInfo = controller.GetTypeInfo(); var typeInfo = controller.GetTypeInfo();
// Act // Act
@ -567,7 +593,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void GetActions_MixedHttpVerbsAndRoutes_EmptyVerbWithRoute() public void GetActions_MixedHttpVerbsAndRoutes_EmptyVerbWithRoute()
{ {
// Arrange // Arrange
var builder = new DefaultActionModelBuilder(); var builder = CreateTestDefaultActionModelBuilder();
var typeInfo = typeof(MixedHttpVerbsAndRouteAttributeController).GetTypeInfo(); var typeInfo = typeof(MixedHttpVerbsAndRouteAttributeController).GetTypeInfo();
var actionName = nameof(MixedHttpVerbsAndRouteAttributeController.VerbAndRoute); var actionName = nameof(MixedHttpVerbsAndRouteAttributeController.VerbAndRoute);
@ -584,7 +610,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void GetActions_MixedHttpVerbsAndRoutes_MultipleEmptyVerbsWithMultipleRoutes() public void GetActions_MixedHttpVerbsAndRoutes_MultipleEmptyVerbsWithMultipleRoutes()
{ {
// Arrange // Arrange
var builder = new DefaultActionModelBuilder(); var builder = CreateTestDefaultActionModelBuilder();
var typeInfo = typeof(MixedHttpVerbsAndRouteAttributeController).GetTypeInfo(); var typeInfo = typeof(MixedHttpVerbsAndRouteAttributeController).GetTypeInfo();
var actionName = nameof(MixedHttpVerbsAndRouteAttributeController.MultipleVerbsAndRoutes); var actionName = nameof(MixedHttpVerbsAndRouteAttributeController.MultipleVerbsAndRoutes);
@ -605,7 +631,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void GetActions_MixedHttpVerbsAndRoutes_MultipleEmptyAndNonEmptyVerbsWithMultipleRoutes() public void GetActions_MixedHttpVerbsAndRoutes_MultipleEmptyAndNonEmptyVerbsWithMultipleRoutes()
{ {
// Arrange // Arrange
var builder = new DefaultActionModelBuilder(); var builder = CreateTestDefaultActionModelBuilder();
var typeInfo = typeof(MixedHttpVerbsAndRouteAttributeController).GetTypeInfo(); var typeInfo = typeof(MixedHttpVerbsAndRouteAttributeController).GetTypeInfo();
var actionName = nameof(MixedHttpVerbsAndRouteAttributeController.MultipleVerbsWithAnyWithoutTemplateAndRoutes); var actionName = nameof(MixedHttpVerbsAndRouteAttributeController.MultipleVerbsWithAnyWithoutTemplateAndRoutes);
@ -629,7 +655,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void GetActions_MixedHttpVerbsAndRoutes_MultipleEmptyAndNonEmptyVerbs() public void GetActions_MixedHttpVerbsAndRoutes_MultipleEmptyAndNonEmptyVerbs()
{ {
// Arrange // Arrange
var builder = new DefaultActionModelBuilder(); var builder = CreateTestDefaultActionModelBuilder();
var typeInfo = typeof(MixedHttpVerbsAndRouteAttributeController).GetTypeInfo(); var typeInfo = typeof(MixedHttpVerbsAndRouteAttributeController).GetTypeInfo();
var actionName = nameof(MixedHttpVerbsAndRouteAttributeController.Invalid); var actionName = nameof(MixedHttpVerbsAndRouteAttributeController.Invalid);
@ -646,8 +672,25 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
Assert.Equal<string>(new string[] { "GET" }, action.HttpMethods); Assert.Equal<string>(new string[] { "GET" }, action.HttpMethods);
} }
private static DefaultActionModelBuilder CreateTestDefaultActionModelBuilder(
AuthorizationOptions authOptions = null)
{
var options = new Mock<IOptions<AuthorizationOptions>>();
options.Setup(o => o.Options).Returns(authOptions ?? new AuthorizationOptions());
return new DefaultActionModelBuilder(options.Object);
}
private static AccessibleActionModelBuilder CreateTestAccessibleActionModelBuilder()
{
var options = new Mock<IOptions<AuthorizationOptions>>();
options.Setup(o => o.Options).Returns(new AuthorizationOptions());
return new AccessibleActionModelBuilder(options.Object);
}
private class AccessibleActionModelBuilder : DefaultActionModelBuilder private class AccessibleActionModelBuilder : DefaultActionModelBuilder
{ {
public AccessibleActionModelBuilder(IOptions<AuthorizationOptions> options) : base(options) { }
public new bool IsAction([NotNull] TypeInfo typeInfo, [NotNull]MethodInfo methodInfo) public new bool IsAction([NotNull] TypeInfo typeInfo, [NotNull]MethodInfo methodInfo)
{ {
return base.IsAction(typeInfo, methodInfo); return base.IsAction(typeInfo, methodInfo);
@ -674,6 +717,12 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
{ {
return base.Redirect(url + "#RedirectOverride"); return base.Redirect(url + "#RedirectOverride");
} }
[Authorize(Policy = "Base")]
public virtual void Authorize()
{
}
} }
private class DerivedController : BaseController private class DerivedController : BaseController
@ -691,6 +740,12 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
{ {
} }
[Authorize(Policy = "Derived")]
public override void Authorize()
{
}
public void GenericMethod<T>() public void GenericMethod<T>()
{ {
} }

View File

@ -2,9 +2,11 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.Filters; using Microsoft.AspNet.Mvc.Filters;
using Microsoft.AspNet.Security;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Mvc.ApplicationModels namespace Microsoft.AspNet.Mvc.ApplicationModels
@ -15,8 +17,9 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void BuildControllerModel_DerivedFromControllerClass_HasFilter() public void BuildControllerModel_DerivedFromControllerClass_HasFilter()
{ {
// Arrange // Arrange
var builder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(), var builder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null),
NullLoggerFactory.Instance); NullLoggerFactory.Instance,
null);
var typeInfo = typeof(StoreController).GetTypeInfo(); var typeInfo = typeof(StoreController).GetTypeInfo();
// Act // Act
@ -27,14 +30,31 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
Assert.IsType<ControllerActionFilter>(filter); Assert.IsType<ControllerActionFilter>(filter);
} }
[Fact]
public void BuildControllerModel_AuthorizeAttributeAddsAuthorizeFilter()
{
// Arrange
var builder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null),
NullLoggerFactory.Instance,
null);
var typeInfo = typeof(AccountController).GetTypeInfo();
// Act
var model = builder.BuildControllerModel(typeInfo);
// Assert
Assert.True(model.Filters.Any(f => f is AuthorizeFilter));
}
// This class has a filter attribute, but doesn't implement any filter interfaces, // This class has a filter attribute, but doesn't implement any filter interfaces,
// so ControllerFilter is not present. // so ControllerFilter is not present.
[Fact] [Fact]
public void BuildControllerModel_ClassWithoutFilterInterfaces_HasNoControllerFilter() public void BuildControllerModel_ClassWithoutFilterInterfaces_HasNoControllerFilter()
{ {
// Arrange // Arrange
var builder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(), var builder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null),
NullLoggerFactory.Instance); NullLoggerFactory.Instance,
null);
var typeInfo = typeof(NoFiltersController).GetTypeInfo(); var typeInfo = typeof(NoFiltersController).GetTypeInfo();
// Act // Act
@ -49,8 +69,9 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void BuildControllerModel_ClassWithFilterInterfaces_HasFilter() public void BuildControllerModel_ClassWithFilterInterfaces_HasFilter()
{ {
// Arrange // Arrange
var builder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(), var builder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null),
NullLoggerFactory.Instance); NullLoggerFactory.Instance,
null);
var typeInfo = typeof(SomeFiltersController).GetTypeInfo(); var typeInfo = typeof(SomeFiltersController).GetTypeInfo();
// Act // Act
@ -65,8 +86,9 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
public void BuildControllerModel_ClassWithFilterInterfaces_UnsupportedType() public void BuildControllerModel_ClassWithFilterInterfaces_UnsupportedType()
{ {
// Arrange // Arrange
var builder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(), var builder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null),
NullLoggerFactory.Instance); NullLoggerFactory.Instance,
null);
var typeInfo = typeof(UnsupportedFiltersController).GetTypeInfo(); var typeInfo = typeof(UnsupportedFiltersController).GetTypeInfo();
// Act // Act
@ -81,11 +103,16 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
} }
[Produces("application/json")] [Produces("application/json")]
private class NoFiltersController public class NoFiltersController
{ {
} }
private class SomeFiltersController : IAsyncActionFilter, IResultFilter [Authorize]
public class AccountController
{
}
public class SomeFiltersController : IAsyncActionFilter, IResultFilter
{ {
public Task OnActionExecutionAsync( public Task OnActionExecutionAsync(
[NotNull] ActionExecutingContext context, [NotNull] ActionExecutingContext context,
@ -121,4 +148,4 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
} }
} }
} }
} }

View File

@ -1363,8 +1363,9 @@ namespace Microsoft.AspNet.Mvc.Test
IEnumerable<IFilter> filters = null) IEnumerable<IFilter> filters = null)
{ {
var controllerTypeProvider = new FixedSetControllerTypeProvider(new[] { controllerTypeInfo }); var controllerTypeProvider = new FixedSetControllerTypeProvider(new[] { controllerTypeInfo });
var controllerModelBuilder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(), var controllerModelBuilder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null),
NullLoggerFactory.Instance); NullLoggerFactory.Instance,
null);
var provider = new ControllerActionDescriptorProvider( var provider = new ControllerActionDescriptorProvider(
controllerTypeProvider, controllerTypeProvider,
@ -1380,8 +1381,9 @@ namespace Microsoft.AspNet.Mvc.Test
params TypeInfo[] controllerTypeInfo) params TypeInfo[] controllerTypeInfo)
{ {
var controllerTypeProvider = new FixedSetControllerTypeProvider(controllerTypeInfo); var controllerTypeProvider = new FixedSetControllerTypeProvider(controllerTypeInfo);
var controllerModelBuilder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(), var controllerModelBuilder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null),
NullLoggerFactory.Instance); NullLoggerFactory.Instance,
null);
var provider = new ControllerActionDescriptorProvider( var provider = new ControllerActionDescriptorProvider(
controllerTypeProvider, controllerTypeProvider,
@ -1398,8 +1400,9 @@ namespace Microsoft.AspNet.Mvc.Test
IApplicationModelConvention convention) IApplicationModelConvention convention)
{ {
var controllerTypeProvider = new FixedSetControllerTypeProvider(new[] { type }); var controllerTypeProvider = new FixedSetControllerTypeProvider(new[] { type });
var modelBuilder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(), var modelBuilder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null),
NullLoggerFactory.Instance); NullLoggerFactory.Instance,
null);
var options = new MockMvcOptionsAccessor(); var options = new MockMvcOptionsAccessor();
options.Options.Conventions.Add(convention); options.Options.Conventions.Add(convention);
@ -1415,8 +1418,9 @@ namespace Microsoft.AspNet.Mvc.Test
private IEnumerable<ActionDescriptor> GetDescriptors(params TypeInfo[] controllerTypeInfos) private IEnumerable<ActionDescriptor> GetDescriptors(params TypeInfo[] controllerTypeInfos)
{ {
var controllerTypeProvider = new FixedSetControllerTypeProvider(controllerTypeInfos); var controllerTypeProvider = new FixedSetControllerTypeProvider(controllerTypeInfos);
var modelBuilder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(), var modelBuilder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null),
NullLoggerFactory.Instance); NullLoggerFactory.Instance,
null);
var provider = new ControllerActionDescriptorProvider( var provider = new ControllerActionDescriptorProvider(
controllerTypeProvider, controllerTypeProvider,

View File

@ -5,6 +5,7 @@ using System.ComponentModel.Design;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using Microsoft.AspNet.Mvc.ApplicationModels; using Microsoft.AspNet.Mvc.ApplicationModels;
using Microsoft.AspNet.Security;
using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.DependencyInjection.NestedProviders; using Microsoft.Framework.DependencyInjection.NestedProviders;
using Microsoft.Framework.Logging; using Microsoft.Framework.Logging;
@ -123,8 +124,9 @@ namespace Microsoft.AspNet.Mvc.Logging
ILoggerFactory loggerFactory, params TypeInfo[] controllerTypeInfo) ILoggerFactory loggerFactory, params TypeInfo[] controllerTypeInfo)
{ {
var controllerTypeProvider = new FixedSetControllerTypeProvider(controllerTypeInfo); var controllerTypeProvider = new FixedSetControllerTypeProvider(controllerTypeInfo);
var modelBuilder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(), var modelBuilder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null),
loggerFactory); loggerFactory,
null);
var provider = new ControllerActionDescriptorProvider( var provider = new ControllerActionDescriptorProvider(
controllerTypeProvider, controllerTypeProvider,

View File

@ -765,8 +765,9 @@ namespace Microsoft.AspNet.Mvc
.ToList(); .ToList();
var controllerTypeProvider = new FixedSetControllerTypeProvider(controllerTypes); var controllerTypeProvider = new FixedSetControllerTypeProvider(controllerTypes);
var modelBuilder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(), var modelBuilder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null),
NullLoggerFactory.Instance); NullLoggerFactory.Instance,
null);
return new ControllerActionDescriptorProvider( return new ControllerActionDescriptorProvider(
controllerTypeProvider, controllerTypeProvider,

View File

@ -1,65 +0,0 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Linq;
using System.Security.Claims;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Routing;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.DependencyInjection.Fallback;
using Moq;
namespace Microsoft.AspNet.Mvc.Core.Test
{
public class AuthorizeAttributeTestsBase
{
protected AuthorizationContext GetAuthorizationContext(Action<ServiceCollection> registerServices, bool anonymous = false)
{
var validUser = new ClaimsPrincipal(
new ClaimsIdentity(
new Claim[] {
new Claim("Permission", "CanViewPage"),
new Claim(ClaimTypes.Role, "Administrator"),
new Claim(ClaimTypes.Role, "User"),
new Claim(ClaimTypes.NameIdentifier, "John")},
"Basic"));
validUser.AddIdentity(
new ClaimsIdentity(
new Claim[] {
new Claim("Permission", "CupBearer"),
new Claim(ClaimTypes.Role, "Token"),
new Claim(ClaimTypes.NameIdentifier, "John Bear")},
"Bearer"));
// ServiceProvider
var serviceCollection = new ServiceCollection();
if (registerServices != null)
{
registerServices(serviceCollection);
}
var serviceProvider = serviceCollection.BuildServiceProvider();
// HttpContext
var httpContext = new Mock<HttpContext>();
httpContext.SetupGet(c => c.User).Returns(anonymous ? null : validUser);
httpContext.SetupGet(c => c.RequestServices).Returns(serviceProvider);
// AuthorizationContext
var actionContext = new ActionContext(
httpContext: httpContext.Object,
routeData: new RouteData(),
actionDescriptor: null
);
var authorizationContext = new AuthorizationContext(
actionContext,
Enumerable.Empty<IFilter>().ToList()
);
return authorizationContext;
}
}
}

View File

@ -1,33 +1,39 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Routing;
using Microsoft.AspNet.Security; using Microsoft.AspNet.Security;
using Microsoft.AspNet.WebUtilities; using Microsoft.AspNet.WebUtilities;
using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.DependencyInjection.Fallback;
using Moq; using Moq;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Mvc.Core.Test namespace Microsoft.AspNet.Mvc.Test
{ {
public class AuthorizeAttributeTests : AuthorizeAttributeTestsBase public class AuthorizeFilterTest
{ {
[Fact]
public void InvalidUser()
{
var authorizationContext = GetAuthorizationContext(services => services.AddAuthorization());
Assert.True(authorizationContext.HttpContext.User.Identities.Any(i => i.IsAuthenticated));
}
[Fact] [Fact]
public async Task Invoke_ValidClaimShouldNotFail() public async Task Invoke_ValidClaimShouldNotFail()
{ {
// Arrange // Arrange
var authorizeAttribute = new AuthorizeAttribute("CanViewPage"); var authorizeFilter = new AuthorizeFilter(new AuthorizationPolicyBuilder().RequiresClaim("Permission", "CanViewPage").Build());
var authorizationContext = GetAuthorizationContext(services => var authorizationContext = GetAuthorizationContext(services => services.AddAuthorization());
{
services.AddAuthorization(null, options =>
{
var policy = new AuthorizationPolicyBuilder().RequiresClaim("Permission", "CanViewPage");
options.AddPolicy("CanViewPage", policy.Build());
});
});
// Act // Act
await authorizeAttribute.OnAuthorizationAsync(authorizationContext); await authorizeFilter.OnAuthorizationAsync(authorizationContext);
// Assert // Assert
Assert.Null(authorizationContext.Result); Assert.Null(authorizationContext.Result);
@ -38,13 +44,13 @@ namespace Microsoft.AspNet.Mvc.Core.Test
{ {
// Arrange // Arrange
var authorizationOptions = new AuthorizationOptions(); var authorizationOptions = new AuthorizationOptions();
var authorizeAttribute = new AuthorizeAttribute(); var authorizeFilter = new AuthorizeFilter(new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build());
var authorizationContext = GetAuthorizationContext(services => var authorizationContext = GetAuthorizationContext(services =>
services.AddAuthorization(), services.AddAuthorization(),
anonymous: true); anonymous: true);
// Act // Act
await authorizeAttribute.OnAuthorizationAsync(authorizationContext); await authorizeFilter.OnAuthorizationAsync(authorizationContext);
// Assert // Assert
Assert.NotNull(authorizationContext.Result); Assert.NotNull(authorizationContext.Result);
@ -54,7 +60,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test
public async Task Invoke_EmptyClaimsWithAllowAnonymousAttributeShouldNotRejectAnonymousUser() public async Task Invoke_EmptyClaimsWithAllowAnonymousAttributeShouldNotRejectAnonymousUser()
{ {
// Arrange // Arrange
var authorizeAttribute = new AuthorizeAttribute(); var authorizeFilter = new AuthorizeFilter(new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build());
var authorizationContext = GetAuthorizationContext(services => var authorizationContext = GetAuthorizationContext(services =>
{ {
services.AddAuthorization(); services.AddAuthorization();
@ -65,7 +71,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test
authorizationContext.Filters.Add(new AllowAnonymousAttribute()); authorizationContext.Filters.Add(new AllowAnonymousAttribute());
// Act // Act
await authorizeAttribute.OnAuthorizationAsync(authorizationContext); await authorizeFilter.OnAuthorizationAsync(authorizationContext);
// Assert // Assert
Assert.Null(authorizationContext.Result); Assert.Null(authorizationContext.Result);
@ -75,7 +81,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test
public async Task Invoke_EmptyClaimsShouldAuthorizeAuthenticatedUser() public async Task Invoke_EmptyClaimsShouldAuthorizeAuthenticatedUser()
{ {
// Arrange // Arrange
var authorizeAttribute = new AuthorizeAttribute(); var authorizeFilter = new AuthorizeFilter(new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build());
var authorizationContext = GetAuthorizationContext(services => var authorizationContext = GetAuthorizationContext(services =>
{ {
services.AddAuthorization(); services.AddAuthorization();
@ -83,7 +89,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test
}); });
// Act // Act
await authorizeAttribute.OnAuthorizationAsync(authorizationContext); await authorizeFilter.OnAuthorizationAsync(authorizationContext);
// Assert // Assert
Assert.Null(authorizationContext.Result); Assert.Null(authorizationContext.Result);
@ -93,19 +99,15 @@ namespace Microsoft.AspNet.Mvc.Core.Test
public async Task Invoke_SingleValidClaimShouldSucceed() public async Task Invoke_SingleValidClaimShouldSucceed()
{ {
// Arrange // Arrange
var authorizeAttribute = new AuthorizeAttribute("CanViewCommentOrPage"); var authorizeFilter = new AuthorizeFilter(new AuthorizationPolicyBuilder().RequiresClaim("Permission", "CanViewComment", "CanViewPage").Build());
var authorizationContext = GetAuthorizationContext(services => var authorizationContext = GetAuthorizationContext(services =>
{ {
services.AddAuthorization(null, options => services.AddAuthorization();
{
var policy = new AuthorizationPolicyBuilder().RequiresClaim("Permission", "CanViewComment", "CanViewPage");
options.AddPolicy("CanViewCommentOrPage", policy.Build());
});
services.AddTransient<IAuthorizationHandler, DenyAnonymousAuthorizationHandler>(); services.AddTransient<IAuthorizationHandler, DenyAnonymousAuthorizationHandler>();
}); });
// Act // Act
await authorizeAttribute.OnAuthorizationAsync(authorizationContext); await authorizeFilter.OnAuthorizationAsync(authorizationContext);
// Assert // Assert
Assert.Null(authorizationContext.Result); Assert.Null(authorizationContext.Result);
@ -115,7 +117,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test
public async Task Invoke_RequireAdminRoleShouldFailWithNoHandlers() public async Task Invoke_RequireAdminRoleShouldFailWithNoHandlers()
{ {
// Arrange // Arrange
var authorizeAttribute = new AuthorizeAttribute { Roles = "Administrator" }; var authorizeFilter = new AuthorizeFilter(new AuthorizationPolicyBuilder().RequiresRole("Administrator").Build());
var authorizationContext = GetAuthorizationContext(services => var authorizationContext = GetAuthorizationContext(services =>
{ {
services.AddOptions(); services.AddOptions();
@ -123,7 +125,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test
}); });
// Act // Act
await authorizeAttribute.OnAuthorizationAsync(authorizationContext); await authorizeFilter.OnAuthorizationAsync(authorizationContext);
// Assert // Assert
Assert.NotNull(authorizationContext.Result); Assert.NotNull(authorizationContext.Result);
@ -133,7 +135,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test
public async Task Invoke_RequireAdminAndUserRoleWithNoPolicyShouldSucceed() public async Task Invoke_RequireAdminAndUserRoleWithNoPolicyShouldSucceed()
{ {
// Arrange // Arrange
var authorizeAttribute = new AuthorizeAttribute { Roles = "Administrator,User" }; var authorizeFilter = new AuthorizeFilter(new AuthorizationPolicyBuilder().RequiresRole("Administrator").Build());
var authorizationContext = GetAuthorizationContext(services => var authorizationContext = GetAuthorizationContext(services =>
{ {
services.AddAuthorization(); services.AddAuthorization();
@ -141,7 +143,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test
}); });
// Act // Act
await authorizeAttribute.OnAuthorizationAsync(authorizationContext); await authorizeFilter.OnAuthorizationAsync(authorizationContext);
// Assert // Assert
Assert.Null(authorizationContext.Result); Assert.Null(authorizationContext.Result);
@ -151,7 +153,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test
public async Task Invoke_RequireUnknownRoleShouldFail() public async Task Invoke_RequireUnknownRoleShouldFail()
{ {
// Arrange // Arrange
var authorizeAttribute = new AuthorizeAttribute { Roles = "Wut" }; var authorizeFilter = new AuthorizeFilter(new AuthorizationPolicyBuilder().RequiresRole("Wut").Build());
var authorizationContext = GetAuthorizationContext(services => var authorizationContext = GetAuthorizationContext(services =>
{ {
services.AddAuthorization(); services.AddAuthorization();
@ -159,7 +161,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test
}); });
// Act // Act
await authorizeAttribute.OnAuthorizationAsync(authorizationContext); await authorizeFilter.OnAuthorizationAsync(authorizationContext);
// Assert // Assert
Assert.NotNull(authorizationContext.Result); Assert.NotNull(authorizationContext.Result);
@ -169,19 +171,18 @@ namespace Microsoft.AspNet.Mvc.Core.Test
public async Task Invoke_RequireAdminRoleButFailPolicyShouldFail() public async Task Invoke_RequireAdminRoleButFailPolicyShouldFail()
{ {
// Arrange // Arrange
var authorizeAttribute = new AuthorizeAttribute { Roles = "Administrator", Policy = "Basic" }; var authorizeFilter = new AuthorizeFilter(new AuthorizationPolicyBuilder()
.RequiresRole("Administrator")
.RequiresClaim("Permission", "CanViewComment")
.Build());
var authorizationContext = GetAuthorizationContext(services => var authorizationContext = GetAuthorizationContext(services =>
{ {
services.AddAuthorization(null, options => services.AddAuthorization();
{
var policy = new AuthorizationPolicyBuilder().RequiresClaim("Permission", "CanViewComment");
options.AddPolicy("CanViewComment", policy.Build());
});
services.AddTransient<IAuthorizationHandler, DenyAnonymousAuthorizationHandler>(); services.AddTransient<IAuthorizationHandler, DenyAnonymousAuthorizationHandler>();
}); });
// Act // Act
await authorizeAttribute.OnAuthorizationAsync(authorizationContext); await authorizeFilter.OnAuthorizationAsync(authorizationContext);
// Assert // Assert
Assert.NotNull(authorizationContext.Result); Assert.NotNull(authorizationContext.Result);
@ -191,19 +192,17 @@ namespace Microsoft.AspNet.Mvc.Core.Test
public async Task Invoke_InvalidClaimShouldFail() public async Task Invoke_InvalidClaimShouldFail()
{ {
// Arrange // Arrange
var authorizeAttribute = new AuthorizeAttribute("CanViewComment"); var authorizeFilter = new AuthorizeFilter(new AuthorizationPolicyBuilder()
.RequiresClaim("Permission", "CanViewComment")
.Build());
var authorizationContext = GetAuthorizationContext(services => var authorizationContext = GetAuthorizationContext(services =>
{ {
services.AddAuthorization(null, options => services.AddAuthorization();
{
var policy = new AuthorizationPolicyBuilder().RequiresClaim("Permission", "CanViewComment");
options.AddPolicy("CanViewComment", policy.Build());
});
services.AddTransient<IAuthorizationHandler, DenyAnonymousAuthorizationHandler>(); services.AddTransient<IAuthorizationHandler, DenyAnonymousAuthorizationHandler>();
}); });
// Act // Act
await authorizeAttribute.OnAuthorizationAsync(authorizationContext); await authorizeFilter.OnAuthorizationAsync(authorizationContext);
// Assert // Assert
Assert.NotNull(authorizationContext.Result); Assert.NotNull(authorizationContext.Result);
@ -216,14 +215,16 @@ namespace Microsoft.AspNet.Mvc.Core.Test
bool authorizationServiceIsCalled = false; bool authorizationServiceIsCalled = false;
var authorizationService = new Mock<IAuthorizationService>(); var authorizationService = new Mock<IAuthorizationService>();
authorizationService authorizationService
.Setup(x => x.AuthorizeAsync("CanViewComment", null, null)) .Setup(x => x.AuthorizeAsync(null, null, "CanViewComment"))
.Returns(() => .Returns(() =>
{ {
authorizationServiceIsCalled = true; authorizationServiceIsCalled = true;
return Task.FromResult(true); return Task.FromResult(true);
}); });
var authorizeAttribute = new AuthorizeAttribute("CanViewComment"); var authorizeFilter = new AuthorizeFilter(new AuthorizationPolicyBuilder()
.RequiresClaim("Permission", "CanViewComment")
.Build());
var authorizationContext = GetAuthorizationContext(services => var authorizationContext = GetAuthorizationContext(services =>
services.AddInstance(authorizationService.Object) services.AddInstance(authorizationService.Object)
); );
@ -231,7 +232,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test
authorizationContext.Result = new HttpStatusCodeResult(StatusCodes.Status401Unauthorized); authorizationContext.Result = new HttpStatusCodeResult(StatusCodes.Status401Unauthorized);
// Act // Act
await authorizeAttribute.OnAuthorizationAsync(authorizationContext); await authorizeFilter.OnAuthorizationAsync(authorizationContext);
// Assert // Assert
Assert.False(authorizationServiceIsCalled); Assert.False(authorizationServiceIsCalled);
@ -241,19 +242,17 @@ namespace Microsoft.AspNet.Mvc.Core.Test
public async Task Invoke_FailWhenLookingForClaimInOtherIdentity() public async Task Invoke_FailWhenLookingForClaimInOtherIdentity()
{ {
// Arrange // Arrange
var authorizeAttribute = new AuthorizeAttribute("CanViewComment"); var authorizeFilter = new AuthorizeFilter(new AuthorizationPolicyBuilder()
.RequiresClaim("Permission", "CanViewComment")
.Build());
var authorizationContext = GetAuthorizationContext(services => var authorizationContext = GetAuthorizationContext(services =>
{ {
services.AddAuthorization(null, options => services.AddAuthorization();
{
var policy = new AuthorizationPolicyBuilder("Bearer").RequiresClaim("Permission", "CanViewComment");
options.AddPolicy("CanViewComment", policy.Build());
});
services.AddTransient<IAuthorizationHandler, DenyAnonymousAuthorizationHandler>(); services.AddTransient<IAuthorizationHandler, DenyAnonymousAuthorizationHandler>();
}); });
// Act // Act
await authorizeAttribute.OnAuthorizationAsync(authorizationContext); await authorizeFilter.OnAuthorizationAsync(authorizationContext);
// Assert // Assert
Assert.NotNull(authorizationContext.Result); Assert.NotNull(authorizationContext.Result);
@ -263,30 +262,10 @@ namespace Microsoft.AspNet.Mvc.Core.Test
public async Task Invoke_CanLookingForClaimsInMultipleIdentities() public async Task Invoke_CanLookingForClaimsInMultipleIdentities()
{ {
// Arrange // Arrange
var authorizeAttribute = new AuthorizeAttribute("CanViewCommentCupBearer"); var authorizeFilter = new AuthorizeFilter(new AuthorizationPolicyBuilder("Basic", "Bearer")
var authorizationContext = GetAuthorizationContext(services => .RequiresClaim("Permission", "CanViewComment")
{ .RequiresClaim("Permission", "CupBearer")
services.AddAuthorization(null, options => .Build());
{
var policy = new AuthorizationPolicyBuilder("Basic", "Bearer")
.RequiresClaim("Permission", "CanViewComment")
.RequiresClaim("Permission", "CupBearer");
options.AddPolicy("CanViewComment", policy.Build());
});
services.AddTransient<IAuthorizationHandler, DenyAnonymousAuthorizationHandler>();
});
// Act
await authorizeAttribute.OnAuthorizationAsync(authorizationContext);
// Assert
Assert.NotNull(authorizationContext.Result);
}
public async Task Invoke_NoPoliciesShouldNotFail()
{
// Arrange
var authorizeAttribute = new AuthorizeAttribute("CanViewPage");
var authorizationContext = GetAuthorizationContext(services => var authorizationContext = GetAuthorizationContext(services =>
{ {
services.AddAuthorization(); services.AddAuthorization();
@ -294,10 +273,80 @@ namespace Microsoft.AspNet.Mvc.Core.Test
}); });
// Act // Act
await authorizeAttribute.OnAuthorizationAsync(authorizationContext); await authorizeFilter.OnAuthorizationAsync(authorizationContext);
// Assert // Assert
Assert.Null(authorizationContext.Result); Assert.NotNull(authorizationContext.Result);
}
[Fact]
public async Task Invoke_EmptyPolicyWillFail()
{
// Arrange
var authorizeFilter = new AuthorizeFilter(new AuthorizationPolicyBuilder().Build());
var authorizationContext = GetAuthorizationContext(services =>
{
services.AddAuthorization();
services.AddTransient<IAuthorizationHandler, DenyAnonymousAuthorizationHandler>();
});
// Act
await authorizeFilter.OnAuthorizationAsync(authorizationContext);
// Assert
Assert.NotNull(authorizationContext.Result);
}
private AuthorizationContext GetAuthorizationContext(Action<ServiceCollection> registerServices, bool anonymous = false)
{
var validUser = new ClaimsPrincipal(
new ClaimsIdentity(
new Claim[] {
new Claim("Permission", "CanViewPage"),
new Claim(ClaimTypes.Role, "Administrator"),
new Claim(ClaimTypes.Role, "User"),
new Claim(ClaimTypes.NameIdentifier, "John")},
"Basic"));
validUser.AddIdentity(
new ClaimsIdentity(
new Claim[] {
new Claim("Permission", "CupBearer"),
new Claim(ClaimTypes.Role, "Token"),
new Claim(ClaimTypes.NameIdentifier, "John Bear")},
"Bearer"));
// ServiceProvider
var serviceCollection = new ServiceCollection();
if (registerServices != null)
{
registerServices(serviceCollection);
}
var serviceProvider = serviceCollection.BuildServiceProvider();
// HttpContext
var httpContext = new Mock<HttpContext>();
httpContext.SetupProperty(c => c.User);
if (!anonymous)
{
httpContext.Object.User = validUser;
}
httpContext.SetupGet(c => c.RequestServices).Returns(serviceProvider);
// AuthorizationContext
var actionContext = new ActionContext(
httpContext: httpContext.Object,
routeData: new RouteData(),
actionDescriptor: null
);
var authorizationContext = new AuthorizationContext(
actionContext,
Enumerable.Empty<IFilter>().ToList()
);
return authorizationContext;
} }
} }
} }

View File

@ -106,8 +106,12 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
Assert.Equal("4", await response.Content.ReadAsStringAsync()); Assert.Equal("4", await response.Content.ReadAsStringAsync());
} }
[Fact]
public async Task CanAuthorizeParticularUsers() [Theory]
[InlineData("AdminRole")]
[InlineData("InteractiveUsers")]
[InlineData("ApiManagers")]
public async Task CanAuthorize(string testAction)
{ {
// Arrange // Arrange
var server = TestServer.Create(_services, _app); var server = TestServer.Create(_services, _app);
@ -115,7 +119,7 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
// Act // Act
var response = await client.GetAsync( var response = await client.GetAsync(
"http://localhost/AuthorizeUser/ReturnHelloWorldOnlyForAuthorizedUser"); "http://localhost/AuthorizeUser/"+testAction);
// Assert // Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(HttpStatusCode.OK, response.StatusCode);

View File

@ -372,8 +372,9 @@ namespace System.Web.Http
var assemblyProvider = new FixedSetAssemblyProvider(); var assemblyProvider = new FixedSetAssemblyProvider();
assemblyProvider.CandidateAssemblies.Add(GetType().GetTypeInfo().Assembly); assemblyProvider.CandidateAssemblies.Add(GetType().GetTypeInfo().Assembly);
var controllerTypeProvider = new NamespaceFilteredControllerTypeProvider(assemblyProvider); var controllerTypeProvider = new NamespaceFilteredControllerTypeProvider(assemblyProvider);
var modelBuilder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(), var modelBuilder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null),
NullLoggerFactory.Instance); NullLoggerFactory.Instance,
null);
var filterProvider = new Mock<IGlobalFilterProvider>(); var filterProvider = new Mock<IGlobalFilterProvider>();
filterProvider filterProvider

View File

@ -3,6 +3,7 @@
using System; using System;
using System.Security.Claims; using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Builder; using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http.Security; using Microsoft.AspNet.Http.Security;
using Microsoft.AspNet.Security; using Microsoft.AspNet.Security;
@ -11,51 +12,21 @@ using Microsoft.Framework.OptionsModel;
namespace FiltersWebSite namespace FiltersWebSite
{ {
public class BasicOptions : AuthenticationOptions
{
public BasicOptions()
{
AuthenticationType = "Basic";
AuthenticationMode = AuthenticationMode.Passive;
}
}
public class AuthorizeBasicMiddleware : AuthenticationMiddleware<BasicOptions> public class AuthorizeBasicMiddleware : AuthenticationMiddleware<BasicOptions>
{ {
public AuthorizeBasicMiddleware( public AuthorizeBasicMiddleware(
RequestDelegate next, RequestDelegate next,
IServiceProvider services, IServiceProvider services,
IOptions<BasicOptions> options) : IOptions<BasicOptions> options,
base(next, services, options, null) string authType) :
{ } base(next, services, options,
new ConfigureOptions<BasicOptions>(o => o.AuthenticationType = authType) { Name = authType })
{
}
protected override AuthenticationHandler<BasicOptions> CreateHandler() protected override AuthenticationHandler<BasicOptions> CreateHandler()
{ {
return new BasicAuthenticationHandler(); return new BasicAuthenticationHandler();
} }
} }
public class BasicAuthenticationHandler : AuthenticationHandler<BasicOptions>
{
protected override void ApplyResponseChallenge()
{
}
protected override void ApplyResponseGrant()
{
}
protected override AuthenticationTicket AuthenticateCore()
{
var id = new ClaimsIdentity(
new Claim[] {
new Claim("Permission", "CanViewPage"),
new Claim(ClaimTypes.Role, "Administrator"),
new Claim(ClaimTypes.NameIdentifier, "John")},
"Basic");
return new AuthenticationTicket(id, new AuthenticationProperties());
}
}
} }

View File

@ -0,0 +1,38 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http.Security;
using Microsoft.AspNet.Security;
using Microsoft.AspNet.Security.Infrastructure;
using Microsoft.Framework.OptionsModel;
namespace FiltersWebSite
{
public class BasicAuthenticationHandler : AuthenticationHandler<BasicOptions>
{
protected override void ApplyResponseChallenge()
{
}
protected override void ApplyResponseGrant()
{
}
protected override AuthenticationTicket AuthenticateCore()
{
var id = new ClaimsIdentity(
new Claim[] {
new Claim("Permission", "CanViewPage"),
new Claim("Manager", "yes"),
new Claim(ClaimTypes.Role, "Administrator"),
new Claim(ClaimTypes.NameIdentifier, "John")
},
Options.AuthenticationType);
return new AuthenticationTicket(id, new AuthenticationProperties());
}
}
}

View File

@ -0,0 +1,22 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http.Security;
using Microsoft.AspNet.Security;
using Microsoft.AspNet.Security.Infrastructure;
using Microsoft.Framework.OptionsModel;
namespace FiltersWebSite
{
public class BasicOptions : AuthenticationOptions
{
public BasicOptions()
{
AuthenticationMode = AuthenticationMode.Passive;
}
}
}

View File

@ -2,15 +2,27 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Mvc; using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Security;
namespace FiltersWebSite namespace FiltersWebSite
{ {
[AuthorizeUser] [Authorize("Api")]
[Authorize("RequireBasic")]
public class AuthorizeUserController : Controller public class AuthorizeUserController : Controller
{ {
[Authorize("CanViewPage")] [Authorize("Api-Manager")]
public string ReturnHelloWorldOnlyForAuthorizedUser() public string ApiManagers()
{
return "Hello World!";
}
[Authorize(Roles = "Administrator")]
public string AdminRole()
{
return "Hello World!";
}
[Authorize("Interactive")]
public string InteractiveUsers()
{ {
return "Hello World!"; return "Hello World!";
} }
@ -27,6 +39,5 @@ namespace FiltersWebSite
{ {
return "Hello World!"; return "Hello World!";
} }
} }
} }

View File

@ -0,0 +1,21 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Security;
using Microsoft.Framework.DependencyInjection;
namespace FiltersWebSite
{
public class ManagerHandler : AuthorizationHandler<OperationAuthorizationRequirement>
{
public override void Handle(Microsoft.AspNet.Security.AuthorizationContext context, OperationAuthorizationRequirement requirement)
{
if (context.User.HasClaim("Manager", "yes"))
{
context.Succeed(requirement);
}
}
}
}

View File

@ -0,0 +1,14 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Security;
namespace FiltersWebSite
{
public static class Operations
{
public static OperationAuthorizationRequirement Edit = new OperationAuthorizationRequirement { Name = "Edit" };
public static OperationAuthorizationRequirement Create = new OperationAuthorizationRequirement { Name = "Create" };
public static OperationAuthorizationRequirement Delete = new OperationAuthorizationRequirement { Name = "Delete" };
}
}

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Security.Claims; using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Builder; using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Mvc; using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Security; using Microsoft.AspNet.Security;
@ -18,23 +19,32 @@ namespace FiltersWebSite
app.UseServices(services => app.UseServices(services =>
{ {
services.AddMvc(configuration); services.AddMvc(configuration);
services.Configure<AuthorizationOptions>(options => services.ConfigureAuthorization(options =>
{ {
// This policy cannot succeed since it has no requirements // This policy cannot succeed since it has no requirements
options.AddPolicy("Impossible", options.AddPolicy("Impossible", policy => { });
new AuthorizationPolicyBuilder() options.AddPolicy("Api", policy =>
.Build()); {
options.AddPolicy("RequireBasic", policy.ActiveAuthenticationTypes.Add("Api");
new AuthorizationPolicyBuilder("Basic") policy.RequiresClaim(ClaimTypes.NameIdentifier);
.RequiresClaim(ClaimTypes.NameIdentifier) });
.Build()); options.AddPolicy("Api-Manager", policy =>
options.AddPolicy("CanViewPage", {
new AuthorizationPolicyBuilder() policy.ActiveAuthenticationTypes.Add("Api");
.RequiresClaim("Permission", "CanViewPage") policy.Requirements.Add(Operations.Edit);
.Build()); });
options.AddPolicy("Interactive", policy =>
{
policy.ActiveAuthenticationTypes.Add("Interactive");
policy.RequiresClaim(ClaimTypes.NameIdentifier)
.RequiresClaim("Permission", "CanViewPage");
});
}); });
services.AddSingleton<RandomNumberFilter>(); services.AddSingleton<RandomNumberFilter>();
services.AddSingleton<RandomNumberService>(); services.AddSingleton<RandomNumberService>();
services.AddTransient<IAuthorizationHandler, ManagerHandler>();
services.Configure<BasicOptions>(o => o.AuthenticationType = "Api", "Api");
services.Configure<BasicOptions>(o => o.AuthenticationType = "Interactive", "Interactive");
services.Configure<MvcOptions>(options => services.Configure<MvcOptions>(options =>
{ {
@ -48,7 +58,8 @@ namespace FiltersWebSite
app.UseErrorReporter(); app.UseErrorReporter();
app.UseMiddleware<AuthorizeBasicMiddleware>(); app.UseMiddleware<AuthorizeBasicMiddleware>("Interactive");
app.UseMiddleware<AuthorizeBasicMiddleware>("Api");
app.UseMvc(routes => app.UseMvc(routes =>
{ {