Reputation: 578
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 ,
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 )
Upvotes: 0
Views: 664
Reputation: 2619
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.
Upvotes: 1