DynamicAuthorization.Mvc.Core 1.2.2

dotnet add package DynamicAuthorization.Mvc.Core --version 1.2.2                
NuGet\Install-Package DynamicAuthorization.Mvc.Core -Version 1.2.2                
此命令打算在 Visual Studio 的包管理器控制台中使用,因为它使用 NuGet 模块的 Install-Package 版本。
<PackageReference Include="DynamicAuthorization.Mvc.Core" Version="1.2.2" />                
对于支持 PackageReference 的项目,将此 XML 节点复制到项目文件中,以引用包。
paket add DynamicAuthorization.Mvc.Core --version 1.2.2                
#r "nuget: DynamicAuthorization.Mvc.Core, 1.2.2"                
#r 指令可用于 F# Interactive 和多语言笔记本。将其复制到交互工具或脚本的源代码中,以引用包。
// Install DynamicAuthorization.Mvc.Core as a Cake Addin
#addin nuget:?package=DynamicAuthorization.Mvc.Core&version=1.2.2

// Install DynamicAuthorization.Mvc.Core as a Cake Tool
#tool nuget:?package=DynamicAuthorization.Mvc.Core&version=1.2.2                

ASP.NET Core MVC 2.1, 3.1, 5.0 和 6.0 的动态基于角色的授权 NuGet

您已经知道 ASP.NET Core 中的角色授权是如何工作的。

[Authorize(Roles = "Administrator")]
public class AdministrationController : Controller
{
}

但是,如果您不想在 Authorize 属性上硬编码角色或创建角色然后在源代码中指定控制器的访问而不修改源代码该怎么办?

DynamicAuthorization 帮助您以最小的努力在不硬编码角色的情况下授权用户。《DynamicAuthorization》建立在 ASP.NET Core Identity 的基础上,并使用身份机制来管理角色和授权用户。

安装 DynamicAuthorization.Mvc.Core NuGet 包

Install-Package DynamicAuthorization.Mvc.Core

dotnet add package DynamicAuthorization.Mvc.Core

然后,在 Startup.ConfigureServices 方法中将 AddDynamicAuthorization() 添加到 IServiceCollection

public void ConfigureServices(IServiceCollection services)
{
    ...
    services
        .AddIdentity<IdentityUser, IdentityRole>(options => options.SignIn.RequireConfirmedAccount = false)
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();
        
    services
        .AddDynamicAuthorization<ApplicationDbContext>(options => options.DefaultAdminUser = "UserName")

您可以通过 DefaultAdminUser 配置设置默认管理员用户名,以便无创建默认管理员角色及其权限即可访问任何地方。

然后安装 JSON 或 SQLSever 存储以保存角色访问。

要安装 DynamicAuthorization.Mvc.JsonStore NuGet 包

Install-Package DynamicAuthorization.Mvc.JsonStore

dotnet add package DynamicAuthorization.Mvc.JsonStore
public void ConfigureServices(IServiceCollection services)
{
        
    services
        .AddDynamicAuthorization<ApplicationDbContext>(options => options.DefaultAdminUser = "UserName")
        .AddJsonStore(options => options.FilePath = "FilePath");

角色访问将保存在一个JSON文件中,您可以指定文件路径的FilePath配置。

或者安装SQLServer存储DynamicAuthorization.Mvc.MsSqlServerStore NuGet包

Install-Package DynamicAuthorization.Mvc.MsSqlServerStore

dotnet add package DynamicAuthorization.Mvc.MsSqlServerStore
public void ConfigureServices(IServiceCollection services)
{
        
    services
        .AddDynamicAuthorization<ApplicationDbContext>(options => options.DefaultAdminUser = "UserName")
        .AddSqlServerStore(options => options.ConnectionString = "ConnectionString");

您可以使用DisplayName属性来装饰控制器和动作,以向用户显示更有意义的名称而不是控制器和动作名称。

[DisplayName("Access Management")]
public class AccessController : Controller
{

    // GET: Access
    [DisplayName("Access List")]
    public async Task<ActionResult> Index()
}

如果不希望自行实现,您也可以使用用于管理角色和分配角色给用户的默认UI。

安装DynamicAuthorization.Mvc.Ui NuGet包

Install-Package DynamicAuthorization.Mvc.Ui

然后将AddUi添加到DynamicAuthorization注册中

services
        .AddDynamicAuthorization<ApplicationDbContext>(options => options.DefaultAdminUser = "UserName")
        .AddJsonStore(options => options.FilePath = "FilePath")
        .AddUi();

使用http://<your-app>/role URL来管理角色和分配访问权限给角色。

create project

使用http://<your-app>/userrole URL来为用户分配角色。

您还可以使用自定义的TageHelper来检查用户是否有权查看内容。创建一个继承自SecureContentTagHelper的自定义标签助手

[HtmlTargetElement("secure-content")]
public class MySecureContentTagHelper : SecureContentTagHelper<ApplicationDbContext>
{
    public MySecureContentTagHelper(
        ApplicationDbContext dbContext,
        DynamicAuthorizationOptions authorizationOptions,
        IRoleAccessStore roleAccessStore
        )
        : base(dbContext, authorizationOptions, roleAccessStore)
    {
    }
}

在每个视图中,在secure-content标签内部包裹内容或锚点标签

<ul class="nav navbar-nav">
    <li><a asp-area="" asp-controller="Home" asp-action="Index">Home</a></li>
    <li><a asp-area="" asp-controller="Home" asp-action="About">About</a></li>
    <li><a asp-area="" asp-controller="Home" asp-action="Contact">Contact</a></li>
    
    <secure-content asp-area="" asp-controller="Role" asp-action="Index">
        <li><a asp-area="" asp-controller="Role" asp-action="Index">Role</a></li>
    </secure-content>
    <secure-content asp-area="" asp-controller="Access" asp-action="Index">
        <li><a asp-area="" asp-controller="Access" asp-action="Index">Access</a></li>
    </secure-content>
</ul>

别忘了将您的标签助手命名空间添加到_ViewImports.cshtml

@using SampleMvcWebApp
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, SampleMvcWebApp

如果您扩展了IdentityUser或更改了用户和角色键,也应该传递用户和角色类型。例如

public class ApplicationDbContext : IdentityDbContext<ApplicationUser> { ... }
public class MySecureContentTagHelper : SecureContentTagHelper<ApplicationDbContext, ApplicationUser> { ... }

public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, int> { ... }
public class MySecureContentTagHelper : SecureContentTagHelper<ApplicationDbContext, ApplicationUser, ApplicationRole, int> { ... }

如果您不希望使用默认的UI,按照以下步骤发现控制器和动作,然后为角色授权,最后将角色分配给用户。下一步是发现控制器和动作。`IMvcControllerDiscovery`返回所有带有[Authorize]属性的控制器和动作。`IMvcControllerDiscovery.GetControllers()`方法返回一个包含MvcControllerInfo的列表

public class MvcControllerInfo
{
    public string Id => $"{AreaName}:{Name}";

    public string Name { get; set; }

    public string DisplayName { get; set; }

    public string AreaName { get; set; }

    public IEnumerable<MvcActionInfo> Actions { get; set; }
}

public class MvcActionInfo
{
    public string Id => $"{ControllerId}:{Name}";

    public string Name { get; set; }

    public string DisplayName { get; set; }

    public string ControllerId { get; set; }
}

下一步是创建一个角色以向其分配访问权限。使用`RoleManager<>来创建角色,使用`IRoleAccessStore来存储角色访问。

var role = new IdentityRole { Name = "RoleName" };
var result = await _roleManager.CreateAsync(role);

var controllers = _mvcControllerDiscovery.GetControllers();
var roleAccess = new RoleAccess
{
    Controllers = controllers.First(),
    RoleId = role.Id
};
await _roleAccessStore.AddRoleAccessAsync(roleAccess);

最后一步是将创建的角色分配给用户

var user = await _userManager.FindByIdAsync("someId");
await _userManager.AddToRolesAsync(user, new [] { "RoleName" });

现在用户只能访问其角色能够访问的控制器和动作。

以下是一个创建角色并向其分配访问权限的示例。

public class RoleViewModel
{
    [Required]
    [StringLength(256, ErrorMessage = "The {0} must be at least {2} characters long.")]
    public string Name { get; set; }

    public IEnumerable<MvcControllerInfo> SelectedControllers { get; set; }
}

[DisplayName("Role Management")]
public class RoleController : Controller
{
    private readonly IMvcControllerDiscovery _mvcControllerDiscovery;
    private readonly IRoleAccessStore _roleAccessStore;
    private readonly RoleManager<IdentityRole> _roleManager;

    public RoleController(
        IMvcControllerDiscovery mvcControllerDiscovery,
        IRoleAccessStore roleAccessStore,
        RoleManager<IdentityRole> roleManager
        )
    {
        _mvcControllerDiscovery = mvcControllerDiscovery;
        _roleManager = roleManager;
        _roleAccessStore = roleAccessStore;
    }

    // GET: Role/Create
    [DisplayName("Create Role")]
    public ActionResult Create()
    {
        var controllers = _mvcControllerDiscovery.GetControllers();
        ViewData["Controllers"] = controllers;

        return View();
    }
    
    // POST: Role/Create
    [HttpPost, ValidateAntiForgeryToken]
    public async Task<ActionResult> Create(RoleViewModel viewModel)
    {
        if (!ModelState.IsValid)
        {
            ViewData["Controllers"] = _mvcControllerDiscovery.GetControllers();
            return View(viewModel);
        }

        var role = new IdentityRole { Name = viewModel.Name };
        var result = await _roleManager.CreateAsync(role);

        if (!result.Succeeded)
        {
            foreach (var error in result.Errors)
                ModelState.AddModelError("", error.Description);

            ViewData["Controllers"] = _mvcControllerDiscovery.GetControllers();
            return View(viewModel);
        }

        if (viewModel.SelectedControllers != null && viewModel.SelectedControllers.Any())
        {
            foreach (var controller in viewModel.SelectedControllers)
                foreach (var action in controller.Actions)
                    action.ControllerId = controller.Id;

            var roleAccess = new RoleAccess
            {
                Controllers = viewModel.SelectedControllers.ToList(),
                RoleId = role.Id
            };
            await _roleAccessStore.AddRoleAccessAsync(roleAccess);
        }

        return RedirectToAction(nameof(Index));
    }
}

查看示例以查看完整的实现。

要自己一步一步地实现DynamicAuthorization,请查看手动分支

产品 兼容和额外的计算目标框架版本。
.NET net5.0 兼容。 net5.0-windows 已计算。 net6.0 兼容。 net6.0-android 已计算。 net6.0-ios 已计算。 net6.0-maccatalyst 已计算。 net6.0-macos 已计算。 net6.0-tvos 已计算。 net6.0-windows 已计算。 net7.0 兼容。 net7.0-android 已计算。 net7.0-ios 已计算。 net7.0-maccatalyst 已计算。 net7.0-macos 已计算。 net7.0-tvos 已计算。 net7.0-windows 已计算。 net8.0 已计算。 net8.0-android 已计算。 net8.0-browser 已计算。 net8.0-ios 已计算。 net8.0-maccatalyst 已计算。 net8.0-macos 已计算。 net8.0-tvos 已计算。 net8.0-windows 已计算。
.NET Core netcoreapp3.1 兼容。
兼容的目标框架
包含的目标框架(在包中)
了解更多关于 目标框架.NET Standard

NuGet 包 (3)

显示依赖 DynamicAuthorization.Mvc.Core 的前三项 NuGet 包

下载
DynamicAuthorization.Mvc.MsSqlServerStore

DynamicAuthorization 的 SQL Server 存储库

DynamicAuthorization.Mvc.Ui

为 DynamicAuthorization 创建角色和角色访问权限的简单 web UI

DynamicAuthorization.Mvc.JsonStore

DynamicAuthorization 的 JSON 存储

GitHub 仓库

此包不受任何流行的 GitHub 仓库的使用。

版本 下载 上次更新
1.2.2 2,284 4/4/2023
1.2.1 1,816 1/16/2022
1.2.0 3,958 3/23/2021
1.1.1 1,743 3/19/2021
1.1.0 1,625 3/16/2021
1.0.3 1,241 1/23/2021
1.0.2 1,548 11/17/2020
1.0.1 1,199 11/3/2020
1.0.0 1,652 4/28/2020