简体   繁体   中英

custom authorization in asp.net core mvc

In asp.net core mvc project , I want to crate new user roles and give permission to each role for controller actions .
Let say , I have a SchoolController , inside this , I have three methods ,

  • CreateSchool
  • UpdateSchool
  • DeleteSchool

And Let's say I have Admin and Staff roles. I want to give access all methods to Admin and give UpdateSchool to Staff .
Meaning is, Admin can Create,Update,Delete School . And Staff can only UpdateSchool .
I will save this roles permission inside database like

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

Ok , let say we have 3 persons here , Person_1, Person_2 and Person_3 .
And they have different roles like

Person_1 ( Admin )
Person_2 ( Staff )
Person_3 ( Staff )

When users access to CreateSchool Controller's action , I want to check if current user has access to this action or not .

[Authorize]
public async Task<IActionResult> CreateSchool(SchoolViewModel model)
{
     //code to create school
}

For this , should I need to use IAuthorizationHandler 's HandleRequirementAsync ?
Where should I retrieve from database and check for user's request ?
Is there any reference that meet with my requirement ??

Note : Roles and Modules will dynamically create in run-time .

Update : Should I use ActionFilter ? ( reference )

You may do this by using requirement and handler.

Create requirement class:

public class HasRoleRequirement: IAuthorizationRequirement { }

Then implement a handler:

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;
    }
}

Register the policy in the ConfigureServices method in Startup.cs:

services.AddAuthorization(options => 
{
    options.AddPolicy("HasRole", policy => policy.Requirements.Add(new HasRoleRequirement()));
}
services.AddSingleton<IAuthorizationHandler, RoleRequirementHandler>();

Use the authorization by decoration your method [Authorize(Policy = "IsInRole")]

For reusability and cleaner code, you may declare the policy name strings as constants in a static class.

See docs .

You will have to implement the methods GetModule . GetRequiredRoles and IsInAnyRole yourself.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM