From 9cadf88cc0d4a038d823612835a1dd8df8a89fe1 Mon Sep 17 00:00:00 2001 From: Nice <2017875139@qq.com> Date: Mon, 7 Mar 2022 08:51:40 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9A=82=E6=97=B6=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Easy.sln | 6 ++++ .../IPermissionDefinitionContext.cs | 10 +++++++ .../IPermissionDefinitionProvider.cs | 15 ++++++++++ .../Abstractions/IPermissionValueProvider.cs | 16 ++++++++++ .../PermissionDefinitionProvider.cs | 17 +++++++++++ .../Contexts/PermissionValueCheckContext.cs | 19 ++++++++++++ .../Easy.Authorization.csproj | 17 +++++++++++ .../Enums/PermissionGrantResult.cs | 22 ++++++++++++++ .../RolePermissionValueProvider.cs | 30 +++++++++++++++++++ .../AuthorizationPolicyProvider.cs | 27 +++++++++++++++++ .../Realizations/PermissionDefinition.cs | 4 +++ .../Realizations/PermissionGroupDefinition.cs | 29 ++++++++++++++++++ .../Realizations/PermissionRequirement.cs | 17 +++++++++++ .../Extensions/ApiResultExtensions.cs | 2 +- 14 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 src/Easy.Authorization/Abstractions/IPermissionDefinitionContext.cs create mode 100644 src/Easy.Authorization/Abstractions/IPermissionDefinitionProvider.cs create mode 100644 src/Easy.Authorization/Abstractions/IPermissionValueProvider.cs create mode 100644 src/Easy.Authorization/Abstractions/PermissionDefinitionProvider.cs create mode 100644 src/Easy.Authorization/Contexts/PermissionValueCheckContext.cs create mode 100644 src/Easy.Authorization/Easy.Authorization.csproj create mode 100644 src/Easy.Authorization/Enums/PermissionGrantResult.cs create mode 100644 src/Easy.Authorization/PermissionValueProviders/RolePermissionValueProvider.cs create mode 100644 src/Easy.Authorization/Realizations/AuthorizationPolicyProvider.cs create mode 100644 src/Easy.Authorization/Realizations/PermissionDefinition.cs create mode 100644 src/Easy.Authorization/Realizations/PermissionGroupDefinition.cs create mode 100644 src/Easy.Authorization/Realizations/PermissionRequirement.cs diff --git a/Easy.sln b/Easy.sln index 422b084..db8803e 100644 --- a/Easy.sln +++ b/Easy.sln @@ -9,6 +9,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Easy.DI", "src\Easy.DI\Easy EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Easy.Result", "src\Easy.Result\Easy.Result.csproj", "{82677F0B-E9CF-4491-8B04-9BF9B04B1534}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Easy.Authorization", "src\Easy.Authorization\Easy.Authorization.csproj", "{1053FAA9-D1E5-4130-91EF-82868C5C2CA0}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -27,6 +29,10 @@ Global {82677F0B-E9CF-4491-8B04-9BF9B04B1534}.Debug|Any CPU.Build.0 = Debug|Any CPU {82677F0B-E9CF-4491-8B04-9BF9B04B1534}.Release|Any CPU.ActiveCfg = Release|Any CPU {82677F0B-E9CF-4491-8B04-9BF9B04B1534}.Release|Any CPU.Build.0 = Release|Any CPU + {1053FAA9-D1E5-4130-91EF-82868C5C2CA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1053FAA9-D1E5-4130-91EF-82868C5C2CA0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1053FAA9-D1E5-4130-91EF-82868C5C2CA0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1053FAA9-D1E5-4130-91EF-82868C5C2CA0}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/Easy.Authorization/Abstractions/IPermissionDefinitionContext.cs b/src/Easy.Authorization/Abstractions/IPermissionDefinitionContext.cs new file mode 100644 index 0000000..2ace967 --- /dev/null +++ b/src/Easy.Authorization/Abstractions/IPermissionDefinitionContext.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Easy.Authorization.Abstractions; +public interface IPermissionDefinitionContext +{ +} diff --git a/src/Easy.Authorization/Abstractions/IPermissionDefinitionProvider.cs b/src/Easy.Authorization/Abstractions/IPermissionDefinitionProvider.cs new file mode 100644 index 0000000..3472a0f --- /dev/null +++ b/src/Easy.Authorization/Abstractions/IPermissionDefinitionProvider.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Easy.Authorization.Abstractions; +public interface IPermissionDefinitionProvider +{ + void PreDefine(IPermissionDefinitionContext context); + + void Define(IPermissionDefinitionContext context); + + void PostDefine(IPermissionDefinitionContext context); +} diff --git a/src/Easy.Authorization/Abstractions/IPermissionValueProvider.cs b/src/Easy.Authorization/Abstractions/IPermissionValueProvider.cs new file mode 100644 index 0000000..d32bca7 --- /dev/null +++ b/src/Easy.Authorization/Abstractions/IPermissionValueProvider.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Easy.Authorization.Abstractions; +interface IPermissionValueProvider +{ + string Name { get; } + + //TODO: Rename to GetResult? (CheckAsync throws exception by naming convention) + Task CheckAsync(PermissionValueCheckContext context); + + Task CheckAsync(PermissionValuesCheckContext context); +} diff --git a/src/Easy.Authorization/Abstractions/PermissionDefinitionProvider.cs b/src/Easy.Authorization/Abstractions/PermissionDefinitionProvider.cs new file mode 100644 index 0000000..eccbb26 --- /dev/null +++ b/src/Easy.Authorization/Abstractions/PermissionDefinitionProvider.cs @@ -0,0 +1,17 @@ +using Easy.DI; + +namespace Easy.Authorization.Abstractions; +public abstract class PermissionDefinitionProvider : IPermissionDefinitionProvider, ITransientDependency +{ + public virtual void PreDefine(IPermissionDefinitionContext context) + { + + } + + public abstract void Define(IPermissionDefinitionContext context); + + public virtual void PostDefine(IPermissionDefinitionContext context) + { + + } +} diff --git a/src/Easy.Authorization/Contexts/PermissionValueCheckContext.cs b/src/Easy.Authorization/Contexts/PermissionValueCheckContext.cs new file mode 100644 index 0000000..11079ff --- /dev/null +++ b/src/Easy.Authorization/Contexts/PermissionValueCheckContext.cs @@ -0,0 +1,19 @@ +using Easy.Authorization.Realizations; +using System.Security.Claims; + +namespace Easy.Authorization.Contexts; + +public class PermissionValueCheckContext +{ + public PermissionDefinition Permission { get; } + + public ClaimsPrincipal Principal { get; } + + public PermissionValueCheckContext( + PermissionDefinition permission, + ClaimsPrincipal principal) + { + Permission = permission; + Principal = principal; + } +} diff --git a/src/Easy.Authorization/Easy.Authorization.csproj b/src/Easy.Authorization/Easy.Authorization.csproj new file mode 100644 index 0000000..335d7b3 --- /dev/null +++ b/src/Easy.Authorization/Easy.Authorization.csproj @@ -0,0 +1,17 @@ + + + + net6.0 + enable + + + + + + + + + + + + diff --git a/src/Easy.Authorization/Enums/PermissionGrantResult.cs b/src/Easy.Authorization/Enums/PermissionGrantResult.cs new file mode 100644 index 0000000..04152eb --- /dev/null +++ b/src/Easy.Authorization/Enums/PermissionGrantResult.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Easy.Authorization.Enums; +public enum PermissionGrantResult +{ + /// + /// 代表当前无法确定是否授予或禁止权限, 返回UnDefined由其他权限值提供程序检查权限. + /// + Undefined, + /// + /// 授予用户权限,如果没有其他的授权值提供程序返回 Prohibited, 那么最后会返回 Granted. + /// + Granted, + /// + /// 禁止授权用户,任何一个授权值提供程序返回了 Prohibited, 那么其他的提供程序返回的值都不再重要. + /// + Prohibited +} diff --git a/src/Easy.Authorization/PermissionValueProviders/RolePermissionValueProvider.cs b/src/Easy.Authorization/PermissionValueProviders/RolePermissionValueProvider.cs new file mode 100644 index 0000000..1243dcc --- /dev/null +++ b/src/Easy.Authorization/PermissionValueProviders/RolePermissionValueProvider.cs @@ -0,0 +1,30 @@ +using Easy.Authorization.Contexts; +using Easy.Authorization.Enums; +using System.Security.Claims; + +namespace Easy.Authorization.PermissionValueProviders; +public class RolePermissionValueProvider +{ + public const string ProviderName = "R"; + + + public override async Task CheckAsync(PermissionValueCheckContext context) + { + var roles = context.Principal?.FindAll(ClaimTypes.Role).Select(c => c.Value).ToArray(); + + if (roles == null || !roles.Any()) + { + return PermissionGrantResult.Undefined; + } + + foreach (var role in roles.Distinct()) + { + if (await PermissionStore.IsGrantedAsync(context.Permission.Name, Name, role)) + { + return PermissionGrantResult.Granted; + } + } + + return PermissionGrantResult.Undefined; + } +} diff --git a/src/Easy.Authorization/Realizations/AuthorizationPolicyProvider.cs b/src/Easy.Authorization/Realizations/AuthorizationPolicyProvider.cs new file mode 100644 index 0000000..4e7bb6a --- /dev/null +++ b/src/Easy.Authorization/Realizations/AuthorizationPolicyProvider.cs @@ -0,0 +1,27 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.Extensions.Options; + +namespace Easy.Authorization.Realizations; +public class CustomAuthorizationPolicyProvider : DefaultAuthorizationPolicyProvider +{ + public CustomAuthorizationPolicyProvider(IOptions options) : base(options) + { + } + + public override async Task GetPolicyAsync(string policyName) + { + var policy = await base.GetPolicyAsync(policyName); + if (policy != null) + { + return policy; + } + + //TODO: Optimize & Cache! + var policyBuilder = new AuthorizationPolicyBuilder(Array.Empty()); + policyBuilder.Requirements.Add(new PermissionRequirement(policyName)); + return policyBuilder.Build(); + + //return null; + } + +} diff --git a/src/Easy.Authorization/Realizations/PermissionDefinition.cs b/src/Easy.Authorization/Realizations/PermissionDefinition.cs new file mode 100644 index 0000000..059fd3a --- /dev/null +++ b/src/Easy.Authorization/Realizations/PermissionDefinition.cs @@ -0,0 +1,4 @@ +namespace Easy.Authorization.Realizations; +public class PermissionDefinition +{ +} diff --git a/src/Easy.Authorization/Realizations/PermissionGroupDefinition.cs b/src/Easy.Authorization/Realizations/PermissionGroupDefinition.cs new file mode 100644 index 0000000..4dc2452 --- /dev/null +++ b/src/Easy.Authorization/Realizations/PermissionGroupDefinition.cs @@ -0,0 +1,29 @@ +using Easy.Authorization.Abstractions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Easy.Authorization.Realizations; +public class PermissionDefinitionContext : IPermissionDefinitionContext +{ + +} +public class PermissionGroupDefinition +{ + public Dictionary Groups { get; } + +} + +public class PermissionDefinition +{ + /// + /// 权限名称 + /// + public string Name { get; set; } + /// + /// 显示名称 + /// + public string DisplayName { get; set; } +} \ No newline at end of file diff --git a/src/Easy.Authorization/Realizations/PermissionRequirement.cs b/src/Easy.Authorization/Realizations/PermissionRequirement.cs new file mode 100644 index 0000000..773c957 --- /dev/null +++ b/src/Easy.Authorization/Realizations/PermissionRequirement.cs @@ -0,0 +1,17 @@ +using Microsoft.AspNetCore.Authorization; + +namespace Easy.Authorization.Realizations; +public class PermissionRequirement : IAuthorizationRequirement +{ + public string PermissionName { get; } + + public PermissionRequirement(string permissionName) + { + PermissionName = permissionName; + } + + public override string ToString() + { + return $"PermissionRequirement: {PermissionName}"; + } +} diff --git a/src/Easy.Result/Extensions/ApiResultExtensions.cs b/src/Easy.Result/Extensions/ApiResultExtensions.cs index cc4f579..441beba 100644 --- a/src/Easy.Result/Extensions/ApiResultExtensions.cs +++ b/src/Easy.Result/Extensions/ApiResultExtensions.cs @@ -39,7 +39,7 @@ public static class ApiResultExtensions } /// /// 自定义状态消息 - /// + /// static public TSource CustomStatusMessage(this TSource source, string status, string message) where TSource : ApiResult {