DTO和总线方案的资源授权 [英] Resource Authorization with DTOs and Bus scenario
问题描述
在ASP.NET Core上,我具有以下控制器:
On an ASP.NET Core I have the following controller:
public class MessageApiController : Controller {
private readonly IMediator _mediator;
public MessageApiController(IMediator mediator) {
_mediator = mediator;
}
[HttpGet("messages")]
public async Task<IActionResult> Get(MessageGetQuery query) {
MessageGetReply reply = await _mediator.SendAsync(query);
return Ok(reply);
}
[HttpDelete("messages")]
public async Task<IActionResult> Delete(MessageDeleteModel model) {
MessageDeleteReply reply = await _mediator.SendAsync(model);
return Ok(reply);
}
}
我有带有方法句柄的处理程序类来执行此操作:
I have handlers classes with a method handle to perform this actions:
获取(为简化起见,短代码)
GET (short code for sake of simplicity)
public async MessageGetReply Handle(MessageGetQuery query) {
IQueryable<Message> messages = _context.Messages.AsQueryable();
messages = messages.Include(x => x.Author).Include(x => x.Recipients);
// Omitted: Filter messages according to query
List<Message> result = await messages.ToListAsync();
// Omitted: Create MessageGetReply from result
} // Handle
删除(为简化起见,短代码)
DELETE (short code for sake of simplicity)
public async MessageDeleteReply Handle(MessageDeleteModel model) {
Message message = await _context.Messages.FirstOrDefaultAsync(x => x.Id == model.Id);
if (message != null) {
_context.Remove(message);
await _context.SaveChangesAsync();
}
// Omitted: Return reply
} // Handle
授权方案如下:
获取
1.用户必须经过身份验证
2. User.Id必须等于Message.RecipientId;
GET
1. The user must be authenticated
2. User.Id must equal Message.RecipientId;
删除
1.用户必须经过身份验证
2. User.Id必须等于Message.AuthorId;
DELETE
1. The user must be authenticated
2. User.Id must equal Message.AuthorId;
因此,我创建了以下资源授权处理程序:
So I created the following resource authorization handler:
public class MessageAuthorizationHandler : AuthorizationHandler<OperationAuthorizationRequirement, Message> {
protected override void Handle(AuthorizationContext context, OperationAuthorizationRequirement requirement, Message resource) {
if (requirement == Operations.Delete) {
if (resource.AuthorId.ToString() == context.User.FindFirstValue(ClaimTypes.NameIdentifier))
context.Succeed(requirement);
}
if (requirement == Operations.Read) {
if (resource.RecipientId.ToString() == context.User.FindFirstValue(ClaimTypes.NameIdentifier)))
context.Succeed(requirement);
}
} // Handle
}
出现一些问题:
-
我应该在GET中将所有消息传递给授权处理程序"吗?
实际上,消息是由MessageGetQuery.AuthorId过滤的...因此授权处理程序可以接收MessageGetQuery.AuthorId而不是List ...但是感觉很奇怪,因为资源是消息列表.MessageGetQuery只是一个DTO.
In fact the messages are filtered by MessageGetQuery.AuthorId ... So the authorization handler could receive MessageGetQuery.AuthorId and not a List ... But feels strange since the resource is the List of Messages. MessageGetQuery is simply a DTO.
授权可以与DTO(查询和模型)结合使用,但这有意义吗?
当DTO的信息少于实体的信息时,就会出现问题,而我需要该信息来做出有关授权的决定...
Authorization could be coupled to DTOs (Query and Model) but does it make sense?
The problem arises when the DTO has less information than the Entity and I need that information to take decisions on authorization ...
如果将实体用作资源,我会失去进行投影的能力:
IQueryable<Message> messages = _context.Messages.AsQueryable();
messages = messages.Include(x => x.Author).Include(x => x.Recipients);
// Omitted: Filter messages according to query
List<Message> result = await messages.ToListAsync();
// CALL authorization and send the resource messages ...
// Omitted: Create MessageGetReply from result
一种解决方案是拥有一个用于读取消息的AuthorizationHandler,一个用于删除消息的AuthorizationHandler ... ...第一个将采用消息列表,第二个将接收消息列表,..但是,我将不得不上许多课.
One solution would be to have a AuthorizationHandler for Read Messages, one AuthorizationHandler for Delete message ... The first one would take a list of messages, the second one message, ... I would however have to many classes.
直接在控制器中使用实体并且没有DTO时,一切都会变得简单,但是恕我直言,不应该这样做...
Everything becomes simpler when using Entities directly in controllers and no DTOs but that, IMHO, should not be done ...
推荐答案
在RC2中,我们删除了auth处理程序中的对象限制,因此您可以使用例如ints.因此,您可以将仓库注入处理程序中,并根据需要拉出DTO.
In RC2 we removed the object restriction in auth handlers, so you'll be able to use, for example, ints. So you could inject your repo into a handler and pull out your DTOs as you wish.
这篇关于DTO和总线方案的资源授权的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!