(ServiceStack) Расположение бизнес-логики в архитектуре, основанной на сообщениях

#security #servicestack

#Безопасность #servicestack

Вопрос:

Какова наилучшая практика для размещения бизнес-логики в дизайне, основанном на сообщениях?

Я использую servicestack для создания моего api.

Вики показан пример размещения RequiredRole атрибута в сообщении вместо службы, обрабатывающей его.

В некотором смысле это [RequiredRole] / [Authenticate] бизнес-логика / безопасность, прикрепленные к сообщению.

Конкретный пример

Скажем, например, я бы добавил DeleteAddress сообщение:

 public class DeleteAddress : IReturn<bool>
{
    public int AddressId { get; set; }
}
  

Но чтобы это было должным образом безопасно, я хочу проверить либо роль администратора, либо разрешение на управление всеми адресами, либо то, что AddressID связан с этим пользователем (возможно, в сеансе, возможно, через вызов db).

Как бы мне лучше всего поступить с этим?

Предложение

Является ли следующий код хорошей практикой, и если да, то как мне его реализовать?

 [RequiredRole("Admin")]
[RequiredPermission("ManageAllAddresses ")]
[RequiredAddressLinkedToAccount]
public class DeleteAddress : IReturn<bool>
{
    public int AddressId { get; set; }
}
  

Комментарии:

1. спасибо за указатель на устаревшие документы в wiki, мы обновим их, чтобы они соответствовали

Ответ №1:

Рекомендация ServiceStack заключается в том, чтобы ваша ServiceModel была свободна от зависимостей, поэтому мы бы рекомендовали вместо этого аннотировать классы реализации вашего сервиса, которые вы можете аннотировать либо к классу Service для применения ко всем операциям, либо к отдельным методам для применения только к этой операции, например:

 [RequiredRole("Admin")]
public class AddressServices : Service
{
    [RequiredPermission("ManageAllAddresses ")]
    [RequiredAddressLinkedToAccount]
    public object Any(DeleteAddress request)
    {
    }
}
  

Пожалуйста, обратите внимание, что ServiceStack требует, чтобы ваши сервисы возвращали ссылочные типы, которые обычно являются DTO ответа, но также могут быть string , например:

 public class DeleteAddress : IReturn<string>
{
    public int AddressId { get; set; }
}
  

Ответ №2:

Чтобы закончить этот вопрос. Я мог бы создать фильтр запросов и добавить его в службу.

Либо наследуется от AuthenticateAttribute, либо непосредственно от RequestFilterAttribute.

 public class RequiredAddressLinkedToAccount : AuthenticateAttribute
{
    public RequiredRoleAttribute(ApplyTo applyTo)
    {
        this.ApplyTo = applyTo;
        this.Priority = (int)RequestFilterPriority.RequiredRole;
    }



    public override void Execute(IRequest req, IResponse res, object requestDto)
    {
        var dto = requestDto as ILinkedToAccount;
        var session = req.GetSession();
        if(dto.AccountId == session.Id)
            return; //we dont want anything to be blocked if the account Id is there.

        //Implement like RequireRoleAttribute
        if (DoHtmlRedirectIfConfigured(req, res)) 
            return;

        res.StatusCode = (int)HttpStatusCode.Forbidden;
        res.StatusDescription = "Address does not belong to you";
        res.EndRequest();

    }
}