aspnetcore/src/Microsoft.AspNetCore.Author.../AuthorizationPolicy.cs

165 lines
6.8 KiB
C#

// 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.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.AspNetCore.Authorization
{
/// <summary>
/// Represents a collection of authorization requirements and the scheme or
/// schemes they are evaluated against, all of which must succeed
/// for authorization to succeed.
/// </summary>
public class AuthorizationPolicy
{
/// <summary>
/// Creates a new instance of <see cref="AuthorizationPolicy"/>.
/// </summary>
/// <param name="requirements">
/// The list of <see cref="IAuthorizationRequirement"/>s which must succeed for
/// this policy to be successful.
/// </param>
/// <param name="authenticationSchemes">
/// The authentication schemes the <paramref name="requirements"/> are evaluated against.
/// </param>
public AuthorizationPolicy(IEnumerable<IAuthorizationRequirement> requirements, IEnumerable<string> authenticationSchemes)
{
if (requirements == null)
{
throw new ArgumentNullException(nameof(requirements));
}
if (authenticationSchemes == null)
{
throw new ArgumentNullException(nameof(authenticationSchemes));
}
if (requirements.Count() == 0)
{
throw new InvalidOperationException(Resources.Exception_AuthorizationPolicyEmpty);
}
Requirements = new List<IAuthorizationRequirement>(requirements).AsReadOnly();
AuthenticationSchemes = new List<string>(authenticationSchemes).AsReadOnly();
}
/// <summary>
/// Gets a readonly list of <see cref="IAuthorizationRequirement"/>s which must succeed for
/// this policy to be successful.
/// </summary>
public IReadOnlyList<IAuthorizationRequirement> Requirements { get; }
/// <summary>
/// Gets a readonly list of the authentication schemes the <see cref="AuthorizationPolicy.Requirements"/>
/// are evaluated against.
/// </summary>
public IReadOnlyList<string> AuthenticationSchemes { get; }
/// <summary>
/// Combines the specified <see cref="AuthorizationPolicy"/> into a single policy.
/// </summary>
/// <param name="policies">The authorization policies to combine.</param>
/// <returns>
/// A new <see cref="AuthorizationPolicy"/> which represents the combination of the
/// specified <paramref name="policies"/>.
/// </returns>
public static AuthorizationPolicy Combine(params AuthorizationPolicy[] policies)
{
if (policies == null)
{
throw new ArgumentNullException(nameof(policies));
}
return Combine((IEnumerable<AuthorizationPolicy>)policies);
}
/// <summary>
/// Combines the specified <see cref="AuthorizationPolicy"/> into a single policy.
/// </summary>
/// <param name="policies">The authorization policies to combine.</param>
/// <returns>
/// A new <see cref="AuthorizationPolicy"/> which represents the combination of the
/// specified <paramref name="policies"/>.
/// </returns>
public static AuthorizationPolicy Combine(IEnumerable<AuthorizationPolicy> policies)
{
if (policies == null)
{
throw new ArgumentNullException(nameof(policies));
}
var builder = new AuthorizationPolicyBuilder();
foreach (var policy in policies)
{
builder.Combine(policy);
}
return builder.Build();
}
/// <summary>
/// Combines the <see cref="AuthorizationPolicy"/> provided by the specified
/// <paramref name="policyProvider"/>.
/// </summary>
/// <param name="policyProvider">A <see cref="IAuthorizationPolicyProvider"/> which provides the policies to combine.</param>
/// <param name="authorizeData">A collection of authorization data used to apply authorization to a resource.</param>
/// <returns>
/// A new <see cref="AuthorizationPolicy"/> which represents the combination of the
/// authorization policies provided by the specified <paramref name="policyProvider"/>.
/// </returns>
public static async Task<AuthorizationPolicy> CombineAsync(IAuthorizationPolicyProvider policyProvider, IEnumerable<IAuthorizeData> authorizeData)
{
if (policyProvider == null)
{
throw new ArgumentNullException(nameof(policyProvider));
}
if (authorizeData == null)
{
throw new ArgumentNullException(nameof(authorizeData));
}
var policyBuilder = new AuthorizationPolicyBuilder();
var any = false;
foreach (var authorizeDatum in authorizeData)
{
any = true;
var useDefaultPolicy = true;
if (!string.IsNullOrWhiteSpace(authorizeDatum.Policy))
{
var policy = await policyProvider.GetPolicyAsync(authorizeDatum.Policy);
if (policy == null)
{
throw new InvalidOperationException(Resources.FormatException_AuthorizationPolicyNotFound(authorizeDatum.Policy));
}
policyBuilder.Combine(policy);
useDefaultPolicy = false;
}
var rolesSplit = authorizeDatum.Roles?.Split(',');
if (rolesSplit != null && rolesSplit.Any())
{
var trimmedRolesSplit = rolesSplit.Where(r => !string.IsNullOrWhiteSpace(r)).Select(r => r.Trim());
policyBuilder.RequireRole(trimmedRolesSplit);
useDefaultPolicy = false;
}
var authTypesSplit = authorizeDatum.AuthenticationSchemes?.Split(',');
if (authTypesSplit != null && authTypesSplit.Any())
{
foreach (var authType in authTypesSplit)
{
if (!string.IsNullOrWhiteSpace(authType))
{
policyBuilder.AuthenticationSchemes.Add(authType.Trim());
}
}
}
if (useDefaultPolicy)
{
policyBuilder.Combine(await policyProvider.GetDefaultPolicyAsync());
}
}
return any ? policyBuilder.Build() : null;
}
}
}