基于策略和资源的授权机制

This commit is contained in:
administrator committed 2024-03-30 21:08:58 +08:00
1 parent 2d0e504108
commit 65925ce6ef
13 files changed
+172 -51

No files matched your search

@@ -0,0 +1,32 @@
using HelloShop.ServiceDefaults.Permissions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization.Infrastructure;
using Microsoft.Extensions.Options;
namespace HelloShop.ServiceDefaults.Authorization;
public class CustomAuthorizationPolicyProvider(IOptions<AuthorizationOptions> options, IPermissionDefinitionManager permissionDefinitionManager) : DefaultAuthorizationPolicyProvider(options)
{
public override async Task<AuthorizationPolicy?> GetPolicyAsync(string policyName)
{
AuthorizationPolicy? policy = await base.GetPolicyAsync(policyName);
if (policy != null)
{
return policy;
}
var permissionDefinition = permissionDefinitionManager.GetOrNullAsync(policyName);
if (permissionDefinition != null)
{
var policyBuilder = new AuthorizationPolicyBuilder();
policyBuilder.Requirements.Add(new OperationAuthorizationRequirement { Name = policyName });
return policyBuilder.Build();
}
return null;
}
}
@@ -0,0 +1,13 @@
using HelloShop.ServiceDefaults.Constants;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Reflection.Metadata.Ecma335;
namespace HelloShop.ServiceDefaults.Authorization;
public interface IAuthorizationResource
{
string ResourceType => GetType().Name;
string ResourceId => GetType().GetProperty(EntityConnstants.DefaultKey)?.GetValue(this)?.ToString() ?? throw new NotImplementedException();
}
@@ -33,7 +33,7 @@ public abstract class PermissionChecker(IHttpContextAccessor httpContextAccessor
await distributedCache.SetObjectAsync(cacheKey, new PermissionGrantCacheItem(isGranted), new DistributedCacheEntryOptions
{
SlidingExpiration = TimeSpan.FromMinutes(10)
AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(1)
});
if (isGranted)
@@ -0,0 +1,29 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization.Infrastructure;
namespace HelloShop.ServiceDefaults.Authorization;
public class PermissionRequirementHandler(IPermissionChecker permissionChecker) : AuthorizationHandler<OperationAuthorizationRequirement>
{
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, OperationAuthorizationRequirement requirement)
{
if (await permissionChecker.IsGrantedAsync(context.User, requirement.Name))
{
context.Succeed(requirement);
return;
}
context.Fail();
}
}
public class ResourcePermissionRequirementHandler(IPermissionChecker permissionChecker) : AuthorizationHandler<OperationAuthorizationRequirement, IAuthorizationResource>
{
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, OperationAuthorizationRequirement requirement, IAuthorizationResource resource)
{
if (await permissionChecker.IsGrantedAsync(context.User, requirement.Name, resource.ResourceType, resource.ResourceId))
{
context.Succeed(requirement);
}
}
}
@@ -0,0 +1,27 @@
namespace HelloShop.ServiceDefaults.Authorization;
public class ResourceInfo : IAuthorizationResource
{
public required string ResourceType { get; set; }
public required string ResourceId { get; set; }
public static implicit operator string(ResourceInfo resource) => resource.ToString();
public static explicit operator ResourceInfo(string resourcePath)
{
string[] separators = resourcePath.Split(":");
if (separators == null || separators.Length != 2)
{
throw new ArgumentException("Resource path must be in the format 'type:id'", nameof(resourcePath));
}
ResourceInfo resourceInfo = new() { ResourceType = separators.First(), ResourceId = separators.Last() };
return resourceInfo;
}
public override string ToString() => $"{ResourceType}:{ResourceId}";
}