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
<PackageReference Include="DynamicAuthorization.Mvc.Ui" Version="1.2.3" />
paket add DynamicAuthorization.Mvc.Ui --version 1.2.3
#r "nuget: DynamicAuthorization.Mvc.Ui, 1.2.3"
// 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 的基于角色的动态授权 
您已经了解 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来管理角色并分配访问权限到角色。
使用 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 仓库使用。