问题
I am trying to implement a Policy that is quite granular level. The idea is like in the image.
Each entity has always the One-To-Many relation with the entity on the right. One Institution can have many Courses, each Course can have many Subjects, each Subject can have many Syllabus, etc...
There are 3 Roles: Administrator
, Contributor
, Viewer
If you have a Role in one of the top entities this role will be propagated to the rest bellow. E.g: If you are an Administrator of Course you are administrator of Subject, Syllabus, etc...
If you are Contributor of one of the Syllabus you will be Contributor for bellow Lessons and Videos of this Syllabus.
I have tried to solve it using Custom Policies
:
Adding a requirement like below:
public class AdministratorRequirement : IAuthorizationRequirement
{
public int UserId { get; private set; }
public EntityType EntityType { get; private set; }
public int EntityId { get; private set; }
public AdministratorRequirement(int userId, EntityType entityType, int entityId)
{
UserId = userId;
EntityType = entityType;
EntityId = entityId;
}
}
And adding the Policy Handler as bellow:
public class AdministratorHandler : AuthorizationHandler<AdministratorRequirement>
{
public IRolesRepository RolesRepository {get;set;}
public AdministratorHandler(IRolesRepository rolesRepository)
{
RolesRepository = rolesRepository;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, AdministratorRequirement requirement)
{
// Save User object to access claims
bool isAdministrator = RolesRepository.CheckUserRole(requirement.UserId, requirement.EntityType, requirement.EntityId, "Administrator");
if (isAdministrator)
context.Succeed(requirement);
return Task.CompletedTask;
}
}
The problem is that I would like to define variable requirement on the Startup class:
options.AddPolicy("CourseAdministrator",
policy => policy
.Requirements
.Add(
new AdministratorRequirement(
/*userId - should be variable*/ 0,
EntityType.Course,
/*int entityId - should be variable*/ 0))
And use it on something like
[Authorize(/*pass some parameters in here like user Id and course Id*/)]
[HttpPost]
[Route("create")]
public async Task<IActionResult> CreateCourse([FromBody] Course course)
{
//Or call the policy handler programatically in here.
CleanCacheOnUpdateCourse();
return Ok(await Services.CreateCourse(course, EmauaUser));
}
Do you know if there is such a solution?
回答1:
For Policy, you need to pass the satic variable.
If you want to check the permission dynamically, you could implement your own IAuthorizationFilter
like
custom
IAuthorizationFilter
public class CustomAuthorize : IAuthorizationFilter { private readonly int _input; public CustomAuthorize(int input) { _input = input; } public void OnAuthorization(AuthorizationFilterContext context) { //custom validation rule if (_input == 1) { context.Result = new ForbidResult(); } } }
Custom
CustomAuthorizeAttribute
public class CustomAuthorizeAttribute : TypeFilterAttribute { public CustomAuthorizeAttribute(int input) : base(typeof(CustomAuthorize)) { Arguments = new object[] { input }; } }
Use
[CustomAuthorizeAttribute(1)] public IActionResult About()
来源:https://stackoverflow.com/questions/58859199/adding-net-core-policy-with-variable-parameters-on-requirements