DynamicAuthorization.Mvc.Ui 1.2.3

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

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

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 帮助您以最小的努力不硬编码角色到 Authorize 属性来授权用户。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

然后向DynamicAuthorization注册中添加 AddUi

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,请按照以下步骤进行操作以发现控制器和操作,然后给角色分配访问权限,然后分配角色(s)到用户。下一步是发现控制器和操作。IMvcControllerDiscovery 返回所有带有 [Authorize] 属性装饰的控制器和操作。《code>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
.NET Core
  • .NETCoreApp 3.1

  • net5.0

  • net6.0

  • net7.0

NuGet 包

此包未被任何 NuGet 包使用。

GitHub 仓库

此包未被任何流行的 GitHub 仓库使用。

版本 下载 最后更新
1.2.3 751 4/4/2023
1.2.1 736 1/16/2022
1.2.0 1,440 3/23/2021
1.1.1 353 3/19/2021
1.1.0 371 3/16/2021
1.0.2 470 11/17/2020
1.0.1 412 11/3/2020
1.0.0 519 4/28/2020