Как ограничить навигационные ссылки HATEOAS на основе разрешений WebAPI? - PullRequest
0 голосов
/ 02 ноября 2019

Я согласен с идеей добавления ссылок типа HATEOAS к данным, возвращаемым из моих маршрутов WebAPI, которые предоставят клиенту подсказки о том, какие действия доступны для любого данного фрагмента данных.

Итак, у меня может быть что-то вроде:

clients: {
  data: [
    {data: {id: 1, name: "Client One", age: 1}, 
     _links: {
       self: {href: ".../api/clients/1}, method: "get"}
       edit: {href: ".../api/clients/1}, method: "put"}
       delete: {href: ".../api/clients/1}, method: "delete"}
     }
    }
  ],
  _links: {
    self: {href: ".../api/clients", method: "get"},
    add: {href: ".../api/clients", method: "post"}
  }
}

Я видел несколько постов, в которых говорится о том, как включить ссылки, чтобы эта часть не была проблемой.

Проблема

Часть идеи, стоящей за HATEOAS, заключается в том, чтобы сделать ваши данные самоопределяемыми / самопутешествующими. Итак, я хотел бы, чтобы мои _links включали только те, которые доступны пользователю на основании его / ее разрешений. IOW, если пользователю было разрешено Edit клиенту, но не Delete клиенту, тогда _links должен включать редактирование, но не удаление.

Проблема в том, что при генерации ссылокЯ бы на самом деле должен был оценить Authorization Policy Действие / Маршрут, чтобы определить, должна ли быть включена ссылка.

Итак, что-то вроде этого (это предназначено для обсуждения, а не на самом делеcode):

[Route("api/v1/[controller]")]
[APIController]
[Authorize(Policy="HR")]
public class UsersController : ControllerBase {

   [HttpGet]
   public async Task<IActionResult> GetClients() { 
       var results = new List<dynamic>();
       var list = context.Clients.Select(u => new BasicClient(u.Id, u.Name))
          .ToList();

       foreach(var client in list){
         //If user has access to GetClient Action
         if(??) { 
           client._links.Self.Href = Url.Action("GetClient", new {id = client.Id});
         }

         //If user has access to DeleteClient Action
         if(??) {
           client._links.Delete.Href = Url.Action("DeleteClient", new {id = client.Id});
        }
        ...
   }

   [HttpGet("{id}", Name="GetClient")]
   [Authorize(Policy="ViewClient")]
   public async Task<IActionResult> GetClient(int id){ ... }

   [HttpDelete("{id}", Name="DeleteClient")]
   [Authorize(Policy="DeleteClient")]
   public async Task<IActionResult> DeleteClient(int id) { ... }

Пользователю потребуются разрешения, необходимые для выполнения политик HR и ViewClients, чтобы получить ссылку self, и дополнительно политику DeleteClients для полученияdelete ссылка.

Возможно ли это? Я думаю об этом неправильно? Есть ли лучший способ?

Разъяснение

Хотя можно использовать AuthorizationService для проверки конкретной политики, я пытаюсь избежатьиспользование жестко закодированных политик. Политики уже определены для Controller и Actions, к которым я пытаюсь получить доступ. Я хочу знать, есть ли способ проверить пользователя по Action (и позволить инфраструктуре разобраться, какую политику необходимо применить).

Таким же образом, как Url.Action("GetClient",...) принимаетимя Action и строит правильную ссылку на основе определенных маршрутов, я хочу что-то вроде AuthService.AuthorizeAction("GetClient", User), которое выяснит, какие разрешения необходимы, и если у пользователя есть эти разрешения.

Надеялся, что.NetCore имеет что-то встроенное, что делает это. В противном случае, я полагаю, я мог бы использовать отражение и IAuthorizationService, чтобы сделать это.

1 Ответ

0 голосов
/ 08 ноября 2019

IAuthorizationService - это услуга, которую вы ищете. Вот фрагмент кода:

var result = await authorization.AuthorizeAsync(User, "IsLucky");
IsLucky = result.Succeeded;

Кредит: https://odetocode.com/blogs/scott/archive/2019/05/30/evaluating-asp-net-core-authorization-policies.aspx

...