ASP.NET Core MVC中的自定义授权

时间:2018-10-05 04:27:33

标签: c# authentication authorization asp.net-core-mvc-2.0

在asp.net核心mvc项目中,我要创建新的用户角色并为每个角色授予控制器操作权限。
假设我有一个SchoolController,其中有三个方法

  • CreateSchool
  • UpdateSchool
  • DeleteSchool

假设我有AdminStaff角色。我想将所有方法都授予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

1 个答案:

答案 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

您将必须实现方法GetModuleGetRequiredRolesIsInAnyRole自己。