Контекстная сериализация от конечной точки WebApi на основе разрешений
Я использую Asp.Net Web Api. Я хотел бы иметь возможность отфильтровать определенные поля в объектах ответа на основе прав доступа подключенных клиентов.
Пример:
class Foo
{
[AccessFilter("Uberlord")]
string Wibble { get; set; }
string Wobble { get; set; }
}
При возврате данных в поле Wibble
должен возвращаться только в том случае, если текущий контекст пользователя может удовлетворять значению "Uberlord".
Есть три пути, которые я изучаю, но у меня нет рабочего решения:
- Пользовательский WebApi MediaTypeFormatter.
- Пользовательский json.net IContractResolver.
- Какая-то оболочка AOP для контроллеров, которая манипулирует объектом ответа
Моя проблема с этим:
- Пользовательский форматировщик не кажется подходящим местом для этого, но может быть единственным вариантом.
- Пользовательский сериализатор json не будет иметь доступа к текущему контексту, поэтому мне придется разобраться с этим.
- При использовании первых двух опций вам потребуются конкретные реализации для каждого формата ответа: json, xml, некоторый пользовательский формат и т. Д. Это будет означать, что если поддерживается другой тип ответа, то для предотвращения утечки конфиденциальных данных требуется специальный форматтер / сериализатор.
- Оболочка контроллера AOP потребует много размышлений.
Дополнительным бонусом будет удаление значений из полей объекта входящего запроса с использованием того же механизма.
Я пропустил очевидный крюк? Это было решено другим способом?
2 ответа
На самом деле все было намного проще, чем я думал. Что я не понял, так это то, что DelegatingHandler
может использоваться для управления ответом, а также запросом в конвейере Web Api.
Жизненный цикл сообщения ASP.NET Web API
Делегирующий обработчик
Делегирующие обработчики - это точка расширения в конвейере сообщений, позволяющая вам массировать запрос, прежде чем передать его остальной части конвейера. Ответное сообщение на обратном пути также должно проходить через делегирующий обработчик, поэтому любой ответ также можно отслеживать / фильтровать / обновлять в этой точке расширяемости.
Делегирующие обработчики, если требуется, также могут обойти остальную часть конвейера и отправлять обратно и Http-ответ сами.
пример
Вот пример реализации DelegatingHandler, который может либо манипулировать объектом ответа, либо полностью заменить его.
public class ResponseDataFilterHandler : DelegatingHandler
{
protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return base.SendAsync(request, cancellationToken)
.ContinueWith(task =>
{
var response = task.Result;
//Manipulate content here
var content = response.Content as ObjectContent;
if (content != null && content.Value != null)
{
((SomeObject)content.Value).SomeProperty = null;
}
//Or replace the content
response.Content = new ObjectContent(typeof(object), new object(), new JsonMediaTypeFormatter());
return response;
});
}
}
У меня есть похожий вопрос в работах здесь: ASP.NET WebAPI Условная сериализация на основе роли пользователя
Предлагаемое решение, которое я придумала, состоит в том, чтобы мой ApiController наследовал от BaseApiController, который переопределяет функцию Initalize, чтобы установить соответствующий форматер в зависимости от роли пользователя. Я еще не решил, пойду ли я этим путем, но, возможно, это сработает для вас.
protected override void Initialize(System.Web.Http.Controllers.HttpControllerContext controllerContext)
{
base.Initialize(controllerContext);
// If the user is in a sensitive-data access role
controllerContext.Configuration.Formatters.Add(/*My Formatter*/);
// Otherwise use the default ones added in global app_start that defaults to remove sensitive data
}