Должен ли я использовать IAuthorizationFilter, если я хочу создать ограниченный ресурс ApiKey с помощью ASP.NET MVC4?

У меня есть несколько простых маршрутов, которые я хочу ограничить с помощью простого параметра querystring. Если ключ неправильный или не предоставлен, то я хочу выбросить NotAuthorizedException.

Пожалуйста, не предлагайте использовать WebApi или equiv - я пока не могу в этом сценарии.

Поэтому я не уверен, что я должен реализовать IAuthorizationFilter или реализовать IActionFilter или даже что-то еще.

Моя логика кода?

  • Проверить запрос для ключа.
  • Проверьте мой RavenDb (репозиторий) для пользователя с этим ключом/значением.

Если они не пройдут какие-либо из этих проверок, отбросьте NotAuthorizedException.

Я предполагаю, что тогда я украшу свой метод действия этим фильтром. Я также предполагаю, что мне нужно будет также передать мой репозиторий в этот метод действий?

Любые предложения, пожалуйста?

Ответ 1

Поэтому я не уверен, что я должен внедрять IAuthorizationFilter или реализуя IActionFilter или даже что-то еще.

Вы должны реализовать IAuthorizationFilter:

public class MyAuthorizeAttribute: FilterAttribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationContext filterContext)
    {
        var key = filterContext.HttpContext.Request.QueryString["param_name"];
        if (!IsValid(key))
        {
            // Unauthorized!
            filterContext.Result = new HttpUnauthorizedResult();
        }
    }

    private bool IsValid(string key)
    {
        // You know what to do here => go hit your RavenDb
        // and perform the necessary checks
        throw new NotImplementedException();
    }
}

И если вы хотите использовать инъекцию зависимостей в свой настраиваемый фильтр действий, вы можете взглянуть на following article, в котором вы могли бы реализовать поставщика настраиваемого фильтра (IFilterProvider). У вас может быть отмеченный атрибут, который вы можете использовать в действиях контроллера, а затем у этого настраиваемого поставщика фильтра просто посмотреть, будет ли действие украшено этим атрибутом маркера и применить настраиваемый фильтр авторизации.

Например:

public class MyAuthorizeAttribute: Attribute
{

}

и ваш фильтр авторизации будет реализовывать только IAuthorizationFilter, это не будет FilterAttribute:

public class MyAuthorizationFilter: IAuthorizationFilter
{
    private readonly ISomeRepository repository;
    public class MyAuthorizationFilter(ISomeRepository repository)
    {
        this.repository = repository;
    }

    public void OnAuthorization(AuthorizationContext filterContext)
    {
        var key = filterContext.HttpContext.Request.QueryString["param_name"];
        if (!IsValid(key))
        {
            // Unauthorized!
            filterContext.Result = new HttpUnauthorizedResult();
        }
    }

    private bool IsValid(string key)
    {
        // You know what to do here => go hit your RavenDb
        // and perform the necessary checks
        throw new NotImplementedException();
    }
}

а затем у вас будет поставщик настраиваемого фильтра:

public class MyFilterProvider : IFilterProvider
{
    public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
        if (actionDescriptor.GetCustomAttributes(typeof(MyAuthorizeAttribute), true).Any())
        {
            var filter = DependencyResolver.Current.GetService<MyAuthorizationFilter>();
            yield return new Filter(filter, FilterScope.Global);
        }

        yield break;
    }
}

который будет зарегистрирован в вашем Application_Start:

FilterProviders.Providers.Add(new MyFilterProvider());