在asp.net核心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
的{{1}}?
我应该在哪里从数据库中检索并检查用户的请求?
有没有符合我要求的参考书?
注意:角色和模块将在运行时动态创建。
更新:我应该使用HandleRequirementAsync
吗? (reference)
答案 0 :(得分:1)
您可以通过使用需求和处理程序来做到这一点。
创建需求类别:
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;
}
}
在Startup.cs的ConfigureServices
方法中注册策略:
services.AddAuthorization(options =>
{
options.AddPolicy("HasRole", policy => policy.Requirements.Add(new HasRoleRequirement()));
}
services.AddSingleton<IAuthorizationHandler, RoleRequirementHandler>();
通过装饰您的方法[Authorize(Policy = "IsInRole")]
关于可重用性和更简洁的代码,您可以在静态类中将策略名称字符串声明为常量。
请参见docs。
您将必须实现方法GetModule
。 GetRequiredRoles
和IsInAnyRole
自己。