#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();
}
}