我正在将MVC Core用于我有以下问题的网站。
假设我有两组GroupA和GroupB,这些组有一些实体。实体要么属于GroupA,要么属于GroupB,但不能同时属于GroupA或GroupB。为了保护这些实体的更新,我已经定义了以下政策:
AuthorizationOptions.AddPolicy("UpdateEntityInGroupAPolicy", policy =>
{
policy.RequireClaim("ClaimThatAllowsUpdatingEntityInGroupA");
});
此策略将确保想要更新GroupA中的实体的用户具有声明ClaimThatAllowsUpdatingEntityInGroupA。可以为GroupB创建一个类似的策略,声明ClaimThatAllowsUpdatingEntityInGroupB。
此外,假设GroupA具有id为5的实体,而GroupB具有id为10的实体。如果给定用户(具有声明ClaimThatAllowsUpdatingEntityInGroupA但未声明ClaimThatAllowsUpdatingEntityInGroupB)在url处更新id为5的实体:
http://example.com/entity/5/update
我现在如何确保用户不只是将网址中的5更改为10并实际更新GroupB中ID为10的其他实体?
我希望我对这个问题很清楚,并感谢您提供任何帮助:)
答案 0 :(得分:0)
如果要使用Authorize
属性,则无法执行此操作,因为授权过滤器不了解您的实体。因此,对于您的案例Resource Based Authorization似乎是正确的方法。
首先假设您的实体如下:
public class YourEntity
{
public int Id { get; set; }
public string Group { get; set; }
//...
}
实施基于资源的授权
创建要求:
public class UpdateRequirement : IAuthorizationRequirement
{
}
为需求和实体
创建授权处理程序public class YourEntityAuthorizationHandler : AuthorizationHandler<UpdateRequirement, YourEntity>
{
public override Task HandleRequirementAsync(AuthorizationHandlerContext context,
UpdateRequirement requirement,
YourEntity resource)
{
if(resource.Group == "GroupA" &&
context.User.HasClaim("ClaimThatAllowsUpdatingEntityInGroupA"))
{
context.Succeed(requirement);
}
else if(resource.Group == "GroupB" &&
context.User.HasClaim("ClaimThatAllowsUpdatingEntityInGroupB"))
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
最后在控制器逻辑中使用它:
public async Task<IActionResult> Update([FromServices]IAuthorizationService authorizationService, int id)
{
var entity= _entityRepository.Get(id);
if (entity == null)
{
return new NotFoundResult();
}
if (await _authorizationService.AuthorizeAsync(User, entity, new UpdateRequirement()))
{
return View(entity);
}
else
{
return new ChallengeResult();
}
}
另见@ blowdart的example