c# - asp.net core mvc中的自定义授权
问题描述
在 asp.net core mvc 项目中,我想创建新的用户角色并为每个角色授予控制器操作的权限。
比方说,我有一个SchoolController
,在这个里面,我有三个方法,
- 创建学校
- 更新学校
- 删除学校
假设我有Admin
角色Staff
。我想授予对所有方法的访问权限Admin
并UpdateSchool
授予Staff
.
意思是,管理员可以创建、更新、删除学校。而员工只能 UpdateSchool 。
我将把这个角色权限保存在数据库中,比如
Role
----------------------------------------
RoleId Name
1 Admin
2 Staff
Module
----------------------------------------
ModuleId Name
1 SchoolController/CreateSchool
2 SchoolController/UpdateSchool
3 SchoolController/DeleteSchool
RoleModules (middle table for relation of roles and module )
----------------------------------------
RoleId ModuleId
1 1
1 2
1 3
2 2
好的,假设我们这里有 3 个人,Person_1、Person_2 和 Person_3。
他们有不同的角色,比如
Person_1 ( Admin )
Person_2 ( Staff )
Person_3 ( Staff )
当用户访问CreateSchool
控制器的操作时,我想检查当前用户是否有权访问此操作。
[Authorize]
public async Task<IActionResult> CreateSchool(SchoolViewModel model)
{
//code to create school
}
为此,我应该使用IAuthorizationHandler
'sHandleRequirementAsync
吗?
我应该在哪里从数据库中检索并检查用户的请求?
有没有符合我要求的参考资料??
注意:角色和模块将在运行时动态创建。
更新:我应该使用ActionFilter
吗?(参考)
解决方案
您可以通过使用需求和处理程序来做到这一点。
创建需求类:
public class HasRoleRequirement: IAuthorizationRequirement { }
然后实现一个处理程序:
public class RoleRequirementHandler : AuthorizationHandler<HasRoleRequirement>
{
protected IHttpContextAccessor m_httpContextAccessor;
public RequirementHandlerBase(IHttpContextAccessor httpContextAccessor)
{
m_httpContextAccessor = httpContextAccessor;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, HasRoleRequirement requirement)
{
var requestPath = m_httpContextAccessor.Request.Path;
var module = GetModule(path); // Get your module from DB
var requiredRoles = GetRequiredRoles(module.ModuleId); // Get the required roles for the module/path
bool isAuthorized = IsInAnyRole(m_httpContext.User, requiredRoles); // Check whether the user has any of the required roles
if (isAuthorized)
{
context.Succeed(requirement);
}
else
{
context.Fail();
}
return Task.CompletedTask;
}
}
ConfigureServices
在 Startup.cs的方法中注册策略:
services.AddAuthorization(options =>
{
options.AddPolicy("HasRole", policy => policy.Requirements.Add(new HasRoleRequirement()));
}
services.AddSingleton<IAuthorizationHandler, RoleRequirementHandler>();
通过装饰您的方法使用授权[Authorize(Policy = "IsInRole")]
为了可重用性和更简洁的代码,您可以将策略名称字符串声明为静态类中的常量。
请参阅文档。
您将不得不实现方法GetModule
。GetRequiredRoles
和IsInAnyRole
你自己。
推荐阅读
- node.js - 节点/HAPI:同时连接太多导致网络连接被重置
- c++ - 如何将windows-936写入日志当wchar_t在代码中通过boost.log
- windows - 如何在 CMD 中调用 %random% 与以前的 %random% 相同?
- javascript - 我的 Ajax 函数发出双重请求
- r - 指数衰减适合 r
- visual-studio-2017 - 为什么 Visual Studio 在运行测试之前不复制静态文件?
- java - Vertx 将 zip 文件流式传输到 http 响应
- java - 解析由 | 分隔的单词
- c++ - 在 C++ 中使用扁平数组语法,崩溃取决于宽度/高度
- woocommerce - 在 Woocommerce Checkout 中更改“可选”标签