首页 > 解决方案 > asp.net core mvc中的自定义授权

问题描述

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

假设我有Admin角色Staff。我想授予对所有方法的访问权限AdminUpdateSchool授予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吗?(参考

标签: c#authenticationauthorizationasp.net-core-mvc-2.0

解决方案


您可以通过使用需求和处理程序来做到这一点。

创建需求类:

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

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

请参阅文档

您将不得不实现方法GetModuleGetRequiredRolesIsInAnyRole你自己。


推荐阅读