ASP.NET Core中的自定义权限控制

在开发ASP.NET Core应用程序时,经常需要对用户进行权限控制,以确保只有具备相应权限的用户才能访问特定的控制器或操作。本文将介绍如何实现一个自定义的权限控制机制,以便在ASP.NET Core应用程序中使用简单的属性来控制对控制器或动作方法的访问。

假设已经有一个自行实现的权限管理系统,并且希望在ASP.NET Core应用程序中使用简单的属性来设置控制器或动作方法所需的权限。例如,可能希望使用类似于ASP.NET 4.5中的[Authorize(Roles="Administrator")]这样的属性来控制访问。

准备工作

首先,需要从数据库或其他存储介质中获取用户的权限信息。在本文的例子中,将只展示IUserCache接口的实现,该接口实现了用户的缓存存储库。这些用户具有一个属性,即权限列表。当缓存时间过期或缓存中不存在该用户时,UserCache将重新加载用户。

Nuget包

为了实现自定义权限控制,需要添加以下Nuget包:

  • Microsoft.AspNetCore.Authentication
  • Microsoft.NETCore.App
  • Microsoft.AspNetCore.Mvc.Core

5个步骤实现自定义权限控制

创建一个从ClaimsPrincipal派生的Principal类。这个类重写了IsInRole方法,使用PermissionProvider来检查角色。Principal需要PermissionProvider,它将检查用户的Roles。

public class AppPrincipal : ClaimsPrincipal { private readonly IPermissionProvider _PermissionProvider; public AppPrincipal(IPermissionProvider permissionProvider, IIdentity ntIdentity) : base((ClaimsIdentity)ntIdentity) { _PermissionProvider = permissionProvider; } public override bool IsInRole(string role) { return _PermissionProvider.IsUserAuthorized(this, role); } }

需要一个权限提供者,它能够根据用户的身份来获取权限。

public class PermissionProvider : IPermissionProvider { private readonly IServerConfiguration _ServerConfiguration; private readonly IUserCache _UserCache; private readonly string _AdministratorPermission; public PermissionProvider(IServerConfiguration serverConfiguration, IUserCache userCache) { _ServerConfiguration = serverConfiguration; _UserCache = userCache; _AdministratorPermission = _ServerConfiguration.AdministratorPermissionName; } public bool IsUserAuthorized(IPrincipal principal, string permission) { if (string.IsNullOrWhiteSpace(permission)) return true; var user = _UserCache.GetUserFromPrincipal(principal); if (user == null) return false; // User has Permission and Permission is Valid if (user.ApplicationPermissions.Any(i => i.IsValid && i.Permission.Equals(permission, StringComparison.OrdinalIgnoreCase))) { return true; } // User has Administrator Permission and Permission is Valid if (user.ApplicationPermissions.Any(i => i.IsValid && i.Permission.Equals(_AdministratorPermission, StringComparison.OrdinalIgnoreCase))) { return true; } return false; } }

需要一个自定义属性来执行权限检查。

public class RequiresPermissionAttribute : TypeFilterAttribute { public RequiresPermissionAttribute(params string[] permissions) : base(typeof(RequiresPermissionAttributeExecutor)) { Arguments = new[] { new PermissionAuthorizationRequirement(permissions) }; } private class RequiresPermissionAttributeExecutor : Attribute, IAsyncResourceFilter { private readonly ILogger _logger; private readonly PermissionAuthorizationRequirement _requiredPermissions; private readonly IPermissionProvider _PermissionProvider; public RequiresPermissionAttributeExecutor(ILogger logger, PermissionAuthorizationRequirement requiredPermissions, IPermissionProvider permissionProvider) { _logger = logger; _requiredPermissions = requiredPermissions; _PermissionProvider = permissionProvider; } public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next) { var principal = new AppPrincipal(_PermissionProvider, context.HttpContext.User.Identity); bool isInOneOfThisRole = false; foreach (var item in _requiredPermissions.RequiredPermissions) { if (principal.IsInRole(item)) { isInOneOfThisRole = true; } } if (!isInOneOfThisRole) { context.Result = new UnauthorizedResult(); await context.Result.ExecuteResultAsync(context); } else { await next(); } } } }

授权要求表示在属性中设置的参数。

public class PermissionAuthorizationRequirement : IAuthorizationRequirement { public IEnumerable RequiredPermissions { get; } public PermissionAuthorizationRequirement(IEnumerable requiredPermissions) { RequiredPermissions = requiredPermissions; } }

现在需要在Startup.cs类中设置依赖注入的配置。

public void ConfigureServices(IServiceCollection services) { // Add framework services. services.AddMvc(); services.AddSingleton(); services.AddSingleton(); services.AddTransient(); }

示例

以下是控制器中的示例:

[RequiresPermission(Permission.User)] public class UserAccountController : Controller { public async Task Get() { try { return Ok(); } catch (Exception e) { return BadRequest(e); } } [RequiresPermission(Permission.Manager)] public async Task GetManager() { try { return Ok(); } catch (Exception e) { return BadRequest(e); } } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485