DTO和总线方案的资源授权 [英] Resource Authorization with DTOs and Bus scenario

查看:59
本文介绍了DTO和总线方案的资源授权的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在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

}

出现一些问题:

  1. 我应该在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屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆