На фильтрах авторизации App.net Web Api, как я могу получить доступ к параметрам?

Я начинаю с Web-API Asp.Net, и здесь моя проблема:

Я реализую настраиваемый фильтр авторизации для проверки моего заголовка сообщения, ищущего ключ API. Основываясь на этом ключе API, я извлекаю своего пользователя, а затем я хотел бы узнать, может ли он иметь доступ к некоторым ресурсам. Идентификатор ресурсов, который я хочу проверить, находится в параметрах HTTP-запроса. Но когда я использую метод AuthorizationFilter, список параметров действий пуст.

Как я могу это сделать?

Если я использовал ActionFilter для замены фильтра авторизации, как я могу быть уверен, что это будет первый фильтр? И во всем мире, как я могу указать порядок выполнения фильтров?

Последний вопрос, можно ли добавить некоторые данные "на трубе", которые я мог бы получить на любом фильтре? Что-то вроде хранилища сеансов, но ограничивается запросом?

Спасибо за любой ответ

Ответ 1

Атрибуты авторизации запускаются до запуска привязки параметров, поэтому вы не можете (как вы видели) использовать коллекцию ActionArguments. Вместо этого вам нужно будет использовать запрос uri для параметров запроса и данных маршрута для параметров uri, как показано ниже.

//request at http://localhost/api/foo/id?MyValue=1
public class MyAuthorizationAttribute : AuthorizeAttribute
{
    protected override bool IsAuthorized(HttpActionContext actionContext)
    {
        //will not work as parameter binding has not yet run
        object value;
        actionContext.ActionArguments.TryGetValue("id", out value);

        //Will get you the resource id assuming a default route like /api/foo/{id} 
        var routeData = actionContext.Request.GetRouteData();
        var myId = routeData.Values["id"] as string;

        //uri is still accessible so use this to get query params
        var queryString = HttpUtility.ParseQueryString(actionContext.Request.RequestUri.Query);
        var myQueryParam = queryString["MyValue"];

        //and so on
    }
}

О порядке выполнения:

Существует три разных способа задания порядка выполнения фильтров с использованием FilterScope Enumeration... scope, являющегося глобальным, контроллером и действием. AuthoriseAttribute является "глобальным", и поэтому он

Задает действие перед контроллером.

Если вам нужно указать порядок выполнения в этих трех областях, вы должны прочитать эту статью в блоге здесь, где вам нужно будет реализовать FilterProvider

Чтобы добавить некоторые данные в канал:

Используйте коллекцию свойств по запросу, который эта коллекция доступна для всего запроса.

    protected override bool IsAuthorized(HttpActionContext actionContext)
    {
        actionContext.Request.Properties.Add("__MYKEY__","MyValue");

        //access this later in the controller or other action filters using
        var value = actionContext.Request.Properties["__MYKEY__"];

    }

Ответ 2

Другой альтернативой для получения параметров является Execute привязка для параметров.

try
{
    var binding = actionContext.ActionDescriptor.ActionBinding;
    var parameters = binding.ParameterBindings.OfType<ModelBinderParameterBinding>();
    var newBinding = new HttpActionBinding(actionContext.ActionDescriptor, parameters.ToArray());
    newBinding.ExecuteBindingAsync(actionContext, new CancellationToken());
    var id = actionContext.ActionArguments["id"] as string;
}
catch
{
    base.HandleUnauthorizedRequest(actionContext);
}

Примечание.. Необходимо убедиться, что вы только фильтруете параметры, которые будут поступать из URI запроса, поскольку я заметил, что выполнение привязки для любых параметров, которые, как ожидается, будут поступать из запроса тело больше не будет передано действительному действию. то есть эти параметры будут нулевыми.

Это просто отметить, что вы можете сделать это, я бы рекомендовал использовать GetRouteData()/RouteData, поскольку он вряд ли нарушит дальнейший поток моделирования ASP.NET MVC.

var routeData = actionContext.ControllerContext.RouteData;
var id = routeData.Values["id"] as string;