asp.net 核心 mvc 中的自定义授权

custom authorization in asp.net core mvc

在 asp.net 核心 mvc 项目中,我想创建新的用户角色并向每个角色授予控制器操作权限。
比方说,我有一个 SchoolController,在这个里面,我有三个方法,

假设我有 AdminStaff 角色。我想将所有方法的访问权限授予 Admin 并将 UpdateSchool 授予 Staff .
意思是,管理员可以创建、更新、删除学校。而 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
}

为此,我需要使用 IAuthorizationHandlerHandleRequirementAsync 吗?
我应该在哪里从数据库中检索并检查用户的请求?
有没有符合我要求的参考资料??

注意:角色和模块将在 运行-time 内动态创建。

更新 :我应该使用 ActionFilter 吗? ( reference )

您可以使用需求和处理程序来完成此操作。

创建需求 class:

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")]

为了可重用性和更简洁的代码,您可以将策略名称字符串声明为静态 class 中的常量。

您将必须实施方法 GetModuleGetRequiredRolesIsInAnyRole 你自己。