Add IAuthorizationPolicyProvider support

This commit is contained in:
Hao Kung 2016-01-27 13:36:53 -08:00
parent 9c41eb958e
commit 00ceeb0262
6 changed files with 126 additions and 9 deletions

View File

@ -26,6 +26,7 @@ namespace Microsoft.Extensions.DependencyInjection
}
services.TryAdd(ServiceDescriptor.Transient<IAuthorizationService, DefaultAuthorizationService>());
services.TryAdd(ServiceDescriptor.Transient<IAuthorizationPolicyProvider, DefaultAuthorizationPolicyProvider>());
services.TryAddEnumerable(ServiceDescriptor.Transient<IAuthorizationHandler, PassThroughAuthorizationHandler>());
return services;
}

View File

@ -0,0 +1,37 @@
// Copyright (c) .NET Foundation. 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.Extensions.Options;
namespace Microsoft.AspNetCore.Authorization
{
/// <summary>
/// A type which can provide a <see cref="AuthorizationPolicy"/> for a particular name.
/// </summary>
public class DefaultAuthorizationPolicyProvider : IAuthorizationPolicyProvider
{
private readonly AuthorizationOptions _options;
public DefaultAuthorizationPolicyProvider(IOptions<AuthorizationOptions> options)
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
_options = options.Value;
}
/// <summary>
/// Gets a <see cref="AuthorizationPolicy"/> from the given <paramref name="policyName"/>
/// </summary>
/// <param name="policyName"></param>
/// <returns></returns>
public virtual Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
{
return Task.FromResult(_options.GetPolicy(policyName));
}
}
}

View File

@ -7,21 +7,20 @@ using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Authorization
{
public class DefaultAuthorizationService : IAuthorizationService
{
private readonly IAuthorizationPolicyProvider _policyProvider;
private readonly IList<IAuthorizationHandler> _handlers;
private readonly AuthorizationOptions _options;
private readonly ILogger _logger;
public DefaultAuthorizationService(IOptions<AuthorizationOptions> options, IEnumerable<IAuthorizationHandler> handlers, ILogger<DefaultAuthorizationService> logger)
public DefaultAuthorizationService(IAuthorizationPolicyProvider policyProvider, IEnumerable<IAuthorizationHandler> handlers, ILogger<DefaultAuthorizationService> logger)
{
if (options == null)
if (policyProvider == null)
{
throw new ArgumentNullException(nameof(options));
throw new ArgumentNullException(nameof(policyProvider));
}
if (handlers == null)
{
@ -33,7 +32,7 @@ namespace Microsoft.AspNetCore.Authorization
}
_handlers = handlers.ToArray();
_options = options.Value;
_policyProvider = policyProvider;
_logger = logger;
}
@ -62,19 +61,19 @@ namespace Microsoft.AspNetCore.Authorization
}
}
public Task<bool> AuthorizeAsync(ClaimsPrincipal user, object resource, string policyName)
public async Task<bool> AuthorizeAsync(ClaimsPrincipal user, object resource, string policyName)
{
if (policyName == null)
{
throw new ArgumentNullException(nameof(policyName));
}
var policy = _options.GetPolicy(policyName);
var policy = await _policyProvider.GetPolicyAsync(policyName);
if (policy == null)
{
throw new InvalidOperationException($"No policy found: {policyName}.");
}
return this.AuthorizeAsync(user, resource, policy);
return await this.AuthorizeAsync(user, resource, policy);
}
}
}

View File

@ -0,0 +1,20 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Threading.Tasks;
namespace Microsoft.AspNetCore.Authorization
{
/// <summary>
/// A type which can provide a <see cref="AuthorizationPolicy"/> for a particular name.
/// </summary>
public interface IAuthorizationPolicyProvider
{
/// <summary>
/// Gets a <see cref="AuthorizationPolicy"/> from the given <paramref name="policyName"/>
/// </summary>
/// <param name="policyName"></param>
/// <returns></returns>
Task<AuthorizationPolicy> GetPolicyAsync(string policyName);
}
}

View File

@ -922,5 +922,64 @@ namespace Microsoft.AspNetCore.Authorization.Test
// Assert
Assert.True(allowed);
}
public class StaticPolicyProvider : IAuthorizationPolicyProvider
{
public Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
{
return Task.FromResult(new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build());
}
}
[Fact]
public async Task CanReplaceDefaultPolicyProvider()
{
var authorizationService = BuildAuthorizationService(services =>
{
// This will ignore the policy options
services.AddSingleton<IAuthorizationPolicyProvider, StaticPolicyProvider>();
services.AddAuthorization(options =>
{
options.AddPolicy("Basic", policy => policy.RequireAssertion(context => true));
});
});
var user = new ClaimsPrincipal();
// Act
var allowed = await authorizationService.AuthorizeAsync(user, "Basic");
// Assert
Assert.False(allowed);
}
public class DynamicPolicyProvider : IAuthorizationPolicyProvider
{
public Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
{
return Task.FromResult(new AuthorizationPolicyBuilder().RequireClaim(policyName).Build());
}
}
[Fact]
public async Task CanUseDynamicPolicyProvider()
{
var authorizationService = BuildAuthorizationService(services =>
{
// This will ignore the policy options
services.AddSingleton<IAuthorizationPolicyProvider, DynamicPolicyProvider>();
services.AddAuthorization(options => { });
});
var id = new ClaimsIdentity();
id.AddClaim(new Claim("1", "1"));
id.AddClaim(new Claim("2", "2"));
var user = new ClaimsPrincipal(id);
// Act
// Assert
Assert.False(await authorizationService.AuthorizeAsync(user, "0"));
Assert.True(await authorizationService.AuthorizeAsync(user, "1"));
Assert.True(await authorizationService.AuthorizeAsync(user, "2"));
Assert.False(await authorizationService.AuthorizeAsync(user, "3"));
}
}
}

View File

@ -4,6 +4,7 @@
},
"dependencies": {
"Microsoft.AspNetCore.Authorization": "1.0.0-*",
"Microsoft.AspNetCore.Testing": "1.0.0-*",
"Microsoft.Extensions.DependencyInjection": "1.0.0-*",
"Microsoft.Extensions.Logging": "1.0.0-*",
"xunit": "2.1.0"