Skip to content
代码片段 群组 项目
未验证 提交 49427139 编辑于 作者: Hao Kung's avatar Hao Kung 提交者: GitHub
浏览文件

Add AuthorizationBuilder (#42264)

上级 36f0f25a
No related branches found
No related tags found
无相关合并请求
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.Authorization;
/// <summary>
/// Used to configure authorization
/// </summary>
public class AuthorizationBuilder
{
/// <summary>
/// Initializes a new instance of <see cref="AuthorizationBuilder"/>.
/// </summary>
/// <param name="services">The services being configured.</param>
public AuthorizationBuilder(IServiceCollection services)
=> Services = services;
/// <summary>
/// The services being configured.
/// </summary>
public virtual IServiceCollection Services { get; }
/// <summary>
/// Determines whether authorization handlers should be invoked after <see cref="AuthorizationHandlerContext.HasFailed"/>.
/// Defaults to true.
/// </summary>
/// <returns>The builder.</returns>
public virtual AuthorizationBuilder SetInvokeHandlersAfterFailure(bool invoke)
{
Services.Configure<AuthorizationOptions>(o => o.InvokeHandlersAfterFailure = invoke);
return this;
}
/// <summary>
/// Sets the default authorization policy. Defaults to require authenticated users.
/// </summary>
/// <remarks>
/// The default policy used when evaluating <see cref="IAuthorizeData"/> with no policy name specified.
/// </remarks>
/// <returns>The builder.</returns>
public virtual AuthorizationBuilder SetDefaultPolicy(AuthorizationPolicy policy)
{
Services.Configure<AuthorizationOptions>(o => o.DefaultPolicy = policy);
return this;
}
/// <summary>
/// Sets the fallback authorization policy used by <see cref="AuthorizationPolicy.CombineAsync(IAuthorizationPolicyProvider, IEnumerable{IAuthorizeData})"/>
/// when no IAuthorizeData have been provided. As a result, the AuthorizationMiddleware uses the fallback policy
/// if there are no <see cref="IAuthorizeData"/> instances for a resource. If a resource has any <see cref="IAuthorizeData"/>
/// then they are evaluated instead of the fallback policy. By default the fallback policy is null, and usually will have no
/// effect unless you have the AuthorizationMiddleware in your pipeline. It is not used in any way by the
/// default <see cref="IAuthorizationService"/>.
/// </summary>
/// <returns>The builder.</returns>
public virtual AuthorizationBuilder SetFallbackPolicy(AuthorizationPolicy? policy)
{
Services.Configure<AuthorizationOptions>(o => o.FallbackPolicy = policy);
return this;
}
/// <summary>
/// Adds a <see cref="AuthorizationPolicy"/> which can be used by <see cref="IAuthorizationService"/>.
/// </summary>
/// <param name="name">The name of this policy.</param>
/// <param name="policy">The <see cref="AuthorizationPolicy"/>.></param>
/// <returns>The builder.</returns>
public virtual AuthorizationBuilder AddPolicy(string name, AuthorizationPolicy policy)
{
Services.Configure<AuthorizationOptions>(o => o.AddPolicy(name, policy));
return this;
}
/// <summary>
/// Add a policy that is built from a delegate with the provided name.
/// </summary>
/// <param name="name">The name of the policy.</param>
/// <param name="configurePolicy">The delegate that will be used to build the policy.</param>
/// <returns>The builder.</returns>
public virtual AuthorizationBuilder AddPolicy(string name, Action<AuthorizationPolicyBuilder> configurePolicy)
{
Services.Configure<AuthorizationOptions>(o => o.AddPolicy(name, configurePolicy));
return this;
}
/// <summary>
/// Add a policy that is built from a delegate with the provided name and used as the default policy.
/// </summary>
/// <param name="name">The name of the default policy.</param>
/// <param name="policy">The default <see cref="AuthorizationPolicy"/>.></param>
/// <returns>The builder.</returns>
public virtual AuthorizationBuilder AddDefaultPolicy(string name, AuthorizationPolicy policy)
{
SetDefaultPolicy(policy);
return AddPolicy(name, policy);
}
/// <summary>
/// Add a policy that is built from a delegate with the provided name and used as the DefaultPolicy.
/// </summary>
/// <param name="name">The name of the DefaultPolicy.</param>
/// <param name="configurePolicy">The delegate that will be used to build the DefaultPolicy.</param>
/// <returns>The builder.</returns>
public virtual AuthorizationBuilder AddDefaultPolicy(string name, Action<AuthorizationPolicyBuilder> configurePolicy)
{
if (configurePolicy == null)
{
throw new ArgumentNullException(nameof(configurePolicy));
}
var policyBuilder = new AuthorizationPolicyBuilder();
configurePolicy(policyBuilder);
return AddDefaultPolicy(name, policyBuilder.Build());
}
/// <summary>
/// Add a policy that is built from a delegate with the provided name and used as the FallbackPolicy.
/// </summary>
/// <param name="name">The name of the FallbackPolicy.</param>
/// <param name="policy">The Fallback <see cref="AuthorizationPolicy"/>.></param>
/// <returns>The builder.</returns>
public virtual AuthorizationBuilder AddFallbackPolicy(string name, AuthorizationPolicy policy)
{
SetFallbackPolicy(policy);
return AddPolicy(name, policy);
}
/// <summary>
/// Add a policy that is built from a delegate with the provided name and used as the FallbackPolicy.
/// </summary>
/// <param name="name">The name of the Fallback policy.</param>
/// <param name="configurePolicy">The delegate that will be used to build the Fallback policy.</param>
/// <returns>The builder.</returns>
public virtual AuthorizationBuilder AddFallbackPolicy(string name, Action<AuthorizationPolicyBuilder> configurePolicy)
{
if (configurePolicy == null)
{
throw new ArgumentNullException(nameof(configurePolicy));
}
var policyBuilder = new AuthorizationPolicyBuilder();
configurePolicy(policyBuilder);
return AddFallbackPolicy(name, policyBuilder.Build());
}
}
......@@ -14,7 +14,7 @@ public class AuthorizationOptions
private Dictionary<string, AuthorizationPolicy> PolicyMap { get; } = new Dictionary<string, AuthorizationPolicy>(StringComparer.OrdinalIgnoreCase);
/// <summary>
/// Determines whether authentication handlers should be invoked after <see cref="AuthorizationHandlerContext.HasFailed"/>.
/// Determines whether authorization handlers should be invoked after <see cref="AuthorizationHandlerContext.HasFailed"/>.
/// Defaults to true.
/// </summary>
public bool InvokeHandlersAfterFailure { get; set; } = true;
......
#nullable enable
Microsoft.AspNetCore.Authorization.AuthorizationBuilder
Microsoft.AspNetCore.Authorization.AuthorizationBuilder.AuthorizationBuilder(Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> void
Microsoft.AspNetCore.Authorization.Infrastructure.PassThroughAuthorizationHandler.PassThroughAuthorizationHandler(Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.Authorization.AuthorizationOptions!>! options) -> void
static Microsoft.AspNetCore.Authorization.AuthorizationPolicy.CombineAsync(Microsoft.AspNetCore.Authorization.IAuthorizationPolicyProvider! policyProvider, System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Authorization.IAuthorizeData!>! authorizeData, System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Authorization.AuthorizationPolicy!>! policies) -> System.Threading.Tasks.Task<Microsoft.AspNetCore.Authorization.AuthorizationPolicy?>!
virtual Microsoft.AspNetCore.Authorization.AuthorizationBuilder.AddDefaultPolicy(string! name, Microsoft.AspNetCore.Authorization.AuthorizationPolicy! policy) -> Microsoft.AspNetCore.Authorization.AuthorizationBuilder!
virtual Microsoft.AspNetCore.Authorization.AuthorizationBuilder.AddDefaultPolicy(string! name, System.Action<Microsoft.AspNetCore.Authorization.AuthorizationPolicyBuilder!>! configurePolicy) -> Microsoft.AspNetCore.Authorization.AuthorizationBuilder!
virtual Microsoft.AspNetCore.Authorization.AuthorizationBuilder.AddFallbackPolicy(string! name, Microsoft.AspNetCore.Authorization.AuthorizationPolicy! policy) -> Microsoft.AspNetCore.Authorization.AuthorizationBuilder!
virtual Microsoft.AspNetCore.Authorization.AuthorizationBuilder.AddFallbackPolicy(string! name, System.Action<Microsoft.AspNetCore.Authorization.AuthorizationPolicyBuilder!>! configurePolicy) -> Microsoft.AspNetCore.Authorization.AuthorizationBuilder!
virtual Microsoft.AspNetCore.Authorization.AuthorizationBuilder.AddPolicy(string! name, Microsoft.AspNetCore.Authorization.AuthorizationPolicy! policy) -> Microsoft.AspNetCore.Authorization.AuthorizationBuilder!
virtual Microsoft.AspNetCore.Authorization.AuthorizationBuilder.AddPolicy(string! name, System.Action<Microsoft.AspNetCore.Authorization.AuthorizationPolicyBuilder!>! configurePolicy) -> Microsoft.AspNetCore.Authorization.AuthorizationBuilder!
virtual Microsoft.AspNetCore.Authorization.AuthorizationBuilder.Services.get -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
virtual Microsoft.AspNetCore.Authorization.AuthorizationBuilder.SetDefaultPolicy(Microsoft.AspNetCore.Authorization.AuthorizationPolicy! policy) -> Microsoft.AspNetCore.Authorization.AuthorizationBuilder!
virtual Microsoft.AspNetCore.Authorization.AuthorizationBuilder.SetFallbackPolicy(Microsoft.AspNetCore.Authorization.AuthorizationPolicy? policy) -> Microsoft.AspNetCore.Authorization.AuthorizationBuilder!
virtual Microsoft.AspNetCore.Authorization.AuthorizationBuilder.SetInvokeHandlersAfterFailure(bool invoke) -> Microsoft.AspNetCore.Authorization.AuthorizationBuilder!
......@@ -12,6 +12,14 @@ namespace Microsoft.Extensions.DependencyInjection;
/// </summary>
public static class PolicyServiceCollectionExtensions
{
/// <summary>
/// Adds authorization services to the specified <see cref="IServiceCollection" />.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection" /> to add services to.</param>
/// <returns>The <see cref="AuthorizationBuilder"/> so that additional calls can be chained.</returns>
public static AuthorizationBuilder AddAuthorizationBuilder(this IServiceCollection services)
=> new AuthorizationBuilder(services.AddAuthorization());
/// <summary>
/// Adds the authorization policy evaluator service to the specified <see cref="IServiceCollection" />.
/// </summary>
......
#nullable enable
static Microsoft.AspNetCore.Builder.AuthorizationEndpointConventionBuilderExtensions.RequireAuthorization<TBuilder>(this TBuilder builder, Microsoft.AspNetCore.Authorization.AuthorizationPolicy! policy) -> TBuilder
static Microsoft.AspNetCore.Builder.AuthorizationEndpointConventionBuilderExtensions.RequireAuthorization<TBuilder>(this TBuilder builder, System.Action<Microsoft.AspNetCore.Authorization.AuthorizationPolicyBuilder!>! configurePolicy) -> TBuilder
static Microsoft.Extensions.DependencyInjection.PolicyServiceCollectionExtensions.AddAuthorizationBuilder(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.AspNetCore.Authorization.AuthorizationBuilder!
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.AspNetCore.Authorization.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Authorization.Test;
public class AuthorizationBuilderTests
{
[Fact]
public void CanSetFallbackPolicy()
{
// Arrange
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
var builder = TestHelpers.CreateAuthorizationBuilder()
// Act
.SetFallbackPolicy(policy);
var options = builder.Services.BuildServiceProvider().GetRequiredService<IOptions<AuthorizationOptions>>().Value;
// Assert
Assert.Equal(policy, options.FallbackPolicy);
}
[Fact]
public void CanUnSetFallbackPolicy()
{
// Arrange
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
var builder = TestHelpers.CreateAuthorizationBuilder()
.SetFallbackPolicy(policy)
// Act
.SetFallbackPolicy(null);
var options = builder.Services.BuildServiceProvider().GetRequiredService<IOptions<AuthorizationOptions>>().Value;
// Assert
Assert.Null(options.FallbackPolicy);
}
[Fact]
public void CanSetDefaultPolicy()
{
// Arrange
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
var builder = TestHelpers.CreateAuthorizationBuilder()
// Act
.SetDefaultPolicy(policy);
var options = builder.Services.BuildServiceProvider().GetRequiredService<IOptions<AuthorizationOptions>>().Value;
// Assert
Assert.Equal(policy, options.DefaultPolicy);
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void CanSetInvokeHandlersAfterFailure(bool invoke)
{
// Arrange
var builder = TestHelpers.CreateAuthorizationBuilder()
// Act
.SetInvokeHandlersAfterFailure(invoke);
var options = builder.Services.BuildServiceProvider().GetRequiredService<IOptions<AuthorizationOptions>>().Value;
// Assert
Assert.Equal(invoke, options.InvokeHandlersAfterFailure);
}
[Fact]
public void CanAddPolicyInstance()
{
// Arrange
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
var builder = TestHelpers.CreateAuthorizationBuilder()
// Act
.AddPolicy("name", policy);
var options = builder.Services.BuildServiceProvider().GetRequiredService<IOptions<AuthorizationOptions>>().Value;
// Assert
Assert.Equal(policy, options.GetPolicy("name"));
}
[Fact]
public void CanAddPolicyDelegate()
{
// Arrange
var builder = TestHelpers.CreateAuthorizationBuilder()
// Act
.AddPolicy("name", p => p.RequireAssertion(_ => true));
var options = builder.Services.BuildServiceProvider().GetRequiredService<IOptions<AuthorizationOptions>>().Value;
// Assert
var policy = options.GetPolicy("name");
Assert.NotNull(policy);
Assert.Equal(1, policy.Requirements.Count);
Assert.IsType<AssertionRequirement>(policy.Requirements.First());
}
}
internal class TestHelpers
{
public static AuthorizationBuilder CreateAuthorizationBuilder()
{
var services = new ServiceCollection();
services.AddLogging();
services.AddOptions();
return services.AddAuthorizationBuilder();
}
}
......@@ -37,12 +37,7 @@ public class DefaultAuthorizationServiceTests
{
// Arrange
var authorizationService = BuildAuthorizationService(services =>
{
services.AddAuthorization(options =>
{
options.AddPolicy("Basic", policy => policy.RequireClaim("Permission", "CanViewPage"));
});
});
services.AddAuthorizationBuilder().AddPolicy("Basic", policy => policy.RequireClaim("Permission", "CanViewPage")));
var user = new ClaimsPrincipal(new ClaimsIdentity(new Claim[] { new Claim("Permission", "CanViewPage") }));
// Act
......@@ -58,13 +53,10 @@ public class DefaultAuthorizationServiceTests
// Arrange
var authorizationService = BuildAuthorizationService(services =>
{
services.AddAuthorization(options =>
services.AddAuthorizationBuilder().AddPolicy("Basic", policy =>
{
options.AddPolicy("Basic", policy =>
{
policy.AddAuthenticationSchemes("Basic");
policy.RequireClaim("Permission", "CanViewPage");
});
policy.AddAuthenticationSchemes("Basic");
policy.RequireClaim("Permission", "CanViewPage");
});
});
var user = new ClaimsPrincipal(new ClaimsIdentity(new Claim[] { new Claim("Permission", "CanViewPage") }, "Basic"));
......@@ -81,12 +73,7 @@ public class DefaultAuthorizationServiceTests
{
// Arrange
var authorizationService = BuildAuthorizationService(services =>
{
services.AddAuthorization(options =>
{
options.AddPolicy("Basic", policy => policy.RequireClaim("Permission", "CanViewPage", "CanViewAnything"));
});
});
services.AddAuthorizationBuilder().AddPolicy("Basic", policy => policy.RequireClaim("Permission", "CanViewPage", "CanViewAnything")));
var user = new ClaimsPrincipal(
new ClaimsIdentity(
new Claim[] {
......@@ -113,10 +100,7 @@ public class DefaultAuthorizationServiceTests
{
services.AddSingleton<IAuthorizationHandler>(handler1);
services.AddSingleton<IAuthorizationHandler>(handler2);
services.AddAuthorization(options =>
{
options.AddPolicy("Custom", policy => policy.Requirements.Add(new CustomRequirement()));
});
services.AddAuthorizationBuilder().AddPolicy("Custom", policy => policy.Requirements.Add(new CustomRequirement()));
});
// Act
......@@ -141,11 +125,9 @@ public class DefaultAuthorizationServiceTests
{
services.AddSingleton<IAuthorizationHandler>(handler1);
services.AddSingleton<IAuthorizationHandler>(handler2);
services.AddAuthorization(options =>
{
options.InvokeHandlersAfterFailure = invokeAllHandlers;
options.AddPolicy("Custom", policy => policy.Requirements.Add(new CustomRequirement()));
});
services.AddAuthorizationBuilder()
.AddPolicy("Custom", policy => policy.Requirements.Add(new CustomRequirement()))
.SetInvokeHandlersAfterFailure(invokeAllHandlers);
});
// Act
......@@ -196,10 +178,7 @@ public class DefaultAuthorizationServiceTests
services.AddSingleton<IAuthorizationHandler>(handler1);
services.AddSingleton<IAuthorizationHandler>(handler2);
services.AddSingleton<IAuthorizationHandler>(handler3);
services.AddAuthorization(options =>
{
options.AddPolicy("Custom", policy => policy.Requirements.Add(new CustomRequirement()));
});
services.AddAuthorizationBuilder().AddPolicy("Custom", policy => policy.Requirements.Add(new CustomRequirement()));
});
// Act
......@@ -222,12 +201,7 @@ public class DefaultAuthorizationServiceTests
{
// Arrange
var authorizationService = BuildAuthorizationService(services =>
{
services.AddAuthorization(options =>
{
options.AddPolicy("Basic", policy => policy.RequireClaim("Permission", "CanViewPage", "CanViewAnything"));
});
});
services.AddAuthorizationBuilder().AddPolicy("Basic", policy => policy.RequireClaim("Permission", "CanViewPage", "CanViewAnything")));
var user = new ClaimsPrincipal(
new ClaimsIdentity(
new Claim[] {
......@@ -249,12 +223,7 @@ public class DefaultAuthorizationServiceTests
{
// Arrange
var authorizationService = BuildAuthorizationService(services =>
{
services.AddAuthorization(options =>
{
options.AddPolicy("Basic", policy => policy.RequireClaim("Permission", "CanViewPage", "CanViewAnything"));
});
});
services.AddAuthorizationBuilder().AddPolicy("Basic", policy => policy.RequireClaim("Permission", "CanViewPage", "CanViewAnything")));
var user = new ClaimsPrincipal(
new ClaimsIdentity(
new Claim[] {
......@@ -275,12 +244,7 @@ public class DefaultAuthorizationServiceTests
{
// Arrange
var authorizationService = BuildAuthorizationService(services =>
{
services.AddAuthorization(options =>
{
options.AddPolicy("Basic", policy => policy.RequireClaim("Permission", "CanViewPage"));
});
});
services.AddAuthorizationBuilder().AddPolicy("Basic", policy => policy.RequireClaim("Permission", "CanViewPage")));
var user = new ClaimsPrincipal(
new ClaimsIdentity(
new Claim[] {
......@@ -301,12 +265,7 @@ public class DefaultAuthorizationServiceTests
{
// Arrange
var authorizationService = BuildAuthorizationService(services =>
{
services.AddAuthorization(options =>
{
options.AddPolicy("Basic", policy => policy.RequireClaim("Permission", "CanViewPage"));
});
});
services.AddAuthorizationBuilder().AddPolicy("Basic", policy => policy.RequireClaim("Permission", "CanViewPage")));
var user = new ClaimsPrincipal(
new ClaimsIdentity(
new Claim[0],
......@@ -325,12 +284,7 @@ public class DefaultAuthorizationServiceTests
{
// Arrange
var authorizationService = BuildAuthorizationService(services =>
{
services.AddAuthorization(options =>
{
options.AddPolicy("Basic", policy => policy.RequireClaim("Permission", "CanViewPage"));
});
});
services.AddAuthorizationBuilder().AddPolicy("Basic", policy => policy.RequireClaim("Permission", "CanViewPage")));
// Act
var allowed = await authorizationService.AuthorizeAsync(null, null, "Basic");
......@@ -344,12 +298,7 @@ public class DefaultAuthorizationServiceTests
{
// Arrange
var authorizationService = BuildAuthorizationService(services =>
{
services.AddAuthorization(options =>
{
options.AddPolicy("Basic", policy => policy.RequireClaim("Permission", "CanViewPage"));
});
});
services.AddAuthorizationBuilder().AddPolicy("Basic", policy => policy.RequireClaim("Permission", "CanViewPage")));
var user = new ClaimsPrincipal(new ClaimsIdentity());
// Act
......@@ -364,12 +313,7 @@ public class DefaultAuthorizationServiceTests
{
// Arrange
var authorizationService = BuildAuthorizationService(services =>
{
services.AddAuthorization(options =>
{
options.AddPolicy("Basic", policy => policy.RequireClaim("Permission", "CanViewPage"));
});
});
services.AddAuthorizationBuilder().AddPolicy("Basic", policy => policy.RequireClaim("Permission", "CanViewPage")));
var user = new ClaimsPrincipal(
new ClaimsIdentity(
new Claim[] {
......@@ -517,12 +461,7 @@ public class DefaultAuthorizationServiceTests
{
// Arrange
var authorizationService = BuildAuthorizationService(services =>
{
services.AddAuthorization(options =>
{
options.AddPolicy("Basic", policy => policy.RequireRole("Admin", "Users"));
});
});
services.AddAuthorizationBuilder().AddPolicy("Basic", policy => policy.RequireRole("Admin", "Users")));
var user = new ClaimsPrincipal(
new ClaimsIdentity(
new Claim[] {
......@@ -541,12 +480,7 @@ public class DefaultAuthorizationServiceTests
public void PolicyThrowsWithNoRequirements()
{
Assert.Throws<InvalidOperationException>(() => BuildAuthorizationService(services =>
{
services.AddAuthorization(options =>
{
options.AddPolicy("Basic", policy => { });
});
}));
services.AddAuthorizationBuilder().AddPolicy("Basic", policy => { })));
}
[Fact]
......@@ -554,12 +488,7 @@ public class DefaultAuthorizationServiceTests
{
// Arrange
var authorizationService = BuildAuthorizationService(services =>
{
services.AddAuthorization(options =>
{
options.AddPolicy("Hao", policy => policy.RequireUserName("Hao"));
});
});
services.AddAuthorizationBuilder().AddPolicy("Hao", policy => policy.RequireUserName("Hao")));
var user = new ClaimsPrincipal(
new ClaimsIdentity(
new Claim[] {
......
0% 加载中 .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册